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
diff options
context:
space:
mode:
authorSebastián Barschkis <sebbas@sebbas.org>2021-02-02 19:51:18 +0300
committerSebastián Barschkis <sebbas@sebbas.org>2021-02-02 19:51:18 +0300
commit1a5b988509fa7a660405dfb8854ea5c34183ef2c (patch)
tree5be12af0eeda5e32f62a96e0f59d3d1b099d74e2
parent4ff5051ffc523d0227dddda6e072befb430743d8 (diff)
parent8c36f6becff2e53e8d545c4c82f3334588140c8f (diff)
Merge branch 'blender-v2.92-release'
-rw-r--r--extern/mantaflow/preprocessed/fileio/iogrids.cpp23
-rw-r--r--extern/mantaflow/preprocessed/fileio/ioparticles.cpp26
-rw-r--r--extern/mantaflow/preprocessed/fileio/ioutil.cpp7
-rw-r--r--extern/mantaflow/preprocessed/fileio/iovdb.cpp153
-rw-r--r--extern/mantaflow/preprocessed/fileio/mantaio.cpp9
-rw-r--r--extern/mantaflow/preprocessed/fileio/mantaio.h3
-rw-r--r--extern/mantaflow/preprocessed/gitinfo.h2
-rw-r--r--extern/mantaflow/preprocessed/grid.cpp6
-rw-r--r--extern/mantaflow/preprocessed/grid.h1
-rw-r--r--extern/mantaflow/preprocessed/grid4d.cpp4
-rw-r--r--intern/mantaflow/intern/MANTA_main.cpp4
-rw-r--r--intern/mantaflow/intern/strings/fluid_script.h2
-rw-r--r--source/blender/blenkernel/intern/fluid.c7
13 files changed, 221 insertions, 26 deletions
diff --git a/extern/mantaflow/preprocessed/fileio/iogrids.cpp b/extern/mantaflow/preprocessed/fileio/iogrids.cpp
index 7cedbb484ba..d138cd2925f 100644
--- a/extern/mantaflow/preprocessed/fileio/iogrids.cpp
+++ b/extern/mantaflow/preprocessed/fileio/iogrids.cpp
@@ -628,13 +628,24 @@ template<class T> int readGridUni(const string &name, Grid<T> *grid)
// current file format
UniHeader head;
assertMsg(gzread(gzf, &head, sizeof(UniHeader)) == sizeof(UniHeader),
- "can't read file, no header present");
- assertMsg(head.dimX == grid->getSizeX() && head.dimY == grid->getSizeY() &&
- head.dimZ == grid->getSizeZ(),
- "grid dim doesn't match, " << Vec3(head.dimX, head.dimY, head.dimZ) << " vs "
- << grid->getSize());
+ "readGridUni: Can't read file, no header present");
assertMsg(unifyGridType(head.gridType) == unifyGridType(grid->getType()),
- "grid type doesn't match " << head.gridType << " vs " << grid->getType());
+ "readGridUni: Grid type doesn't match " << head.gridType << " vs "
+ << grid->getType());
+
+ const Vec3i curGridSize = grid->getParent()->getGridSize();
+ const Vec3i headGridSize(head.dimX, head.dimY, head.dimZ);
+# if BLENDER
+ // Correct grid size is only a soft requirement in Blender
+ if (headGridSize != curGridSize) {
+ debMsg("readGridUni: Grid dim doesn't match, " << headGridSize << " vs " << curGridSize, 1);
+ return 0;
+ }
+# else
+ assertMsg(headGridSize == curGridSize,
+ "readGridUni: Grid dim doesn't match, " << headGridSize << " vs " << curGridSize);
+# endif
+
# if FLOATINGPOINT_PRECISION != 1
// convert float to double
Grid<T> temp(grid->getParent());
diff --git a/extern/mantaflow/preprocessed/fileio/ioparticles.cpp b/extern/mantaflow/preprocessed/fileio/ioparticles.cpp
index 36e10aa1644..538d42f3d87 100644
--- a/extern/mantaflow/preprocessed/fileio/ioparticles.cpp
+++ b/extern/mantaflow/preprocessed/fileio/ioparticles.cpp
@@ -230,6 +230,19 @@ int readParticlesUni(const std::string &name, BasicParticleSystem *parts)
assertMsg(((head.bytesPerElement == PartSysSize) && (head.elementType == 0)),
"particle type doesn't match");
+ const Vec3i curGridSize = parts->getParent()->getGridSize();
+ const Vec3i headGridSize(head.dimX, head.dimY, head.dimZ);
+# if BLENDER
+ // Correct grid size is only a soft requirement in Blender
+ if (headGridSize != curGridSize) {
+ debMsg("readPdataUni: Grid dim doesn't match, " << headGridSize << " vs " << curGridSize, 1);
+ return 0;
+ }
+# else
+ assertMsg(headGridSize == curGridSize,
+ "readPdataUni: Grid dim doesn't match, " << headGridSize << " vs " << curGridSize);
+# endif
+
// re-allocate all data
parts->resizeAll(head.dim);
@@ -325,6 +338,19 @@ template<class T> int readPdataUni(const std::string &name, ParticleDataImpl<T>
pdata->getParticleSys()->resize(head.dim); // ensure that parent particle system has same size
pdata->resize(head.dim);
+ const Vec3i curGridSize = pdata->getParent()->getGridSize();
+ const Vec3i headGridSize(head.dimX, head.dimY, head.dimZ);
+# if BLENDER
+ // Correct grid size is only a soft requirement in Blender
+ if (headGridSize != curGridSize) {
+ debMsg("readPdataUni: Grid dim doesn't match, " << headGridSize << " vs " << curGridSize, 1);
+ return 0;
+ }
+# else
+ assertMsg(headGridSize == curGridSize,
+ "readPdataUni: Grid dim doesn't match, " << headGridSize << " vs " << curGridSize);
+# endif
+
assertMsg(head.dim == pdata->size(), "pdata size doesn't match");
# if FLOATINGPOINT_PRECISION != 1
ParticleDataImpl<T> temp(pdata->getParent());
diff --git a/extern/mantaflow/preprocessed/fileio/ioutil.cpp b/extern/mantaflow/preprocessed/fileio/ioutil.cpp
index 2c7ac7be00e..2bac34c2a65 100644
--- a/extern/mantaflow/preprocessed/fileio/ioutil.cpp
+++ b/extern/mantaflow/preprocessed/fileio/ioutil.cpp
@@ -90,6 +90,13 @@ template<> void convertFrom(openvdb::Vec3s &in, Vec3 *out)
(*out).z = in.z();
}
+template<> void convertFrom(openvdb::Vec3i &in, Vec3i *out)
+{
+ (*out).x = in.x();
+ (*out).y = in.y();
+ (*out).z = in.z();
+}
+
// Convert to OpenVDB value from Manta value.
template<class S, class T> void convertTo(S *out, T &in)
{
diff --git a/extern/mantaflow/preprocessed/fileio/iovdb.cpp b/extern/mantaflow/preprocessed/fileio/iovdb.cpp
index 3641577beca..cc2d0aa508d 100644
--- a/extern/mantaflow/preprocessed/fileio/iovdb.cpp
+++ b/extern/mantaflow/preprocessed/fileio/iovdb.cpp
@@ -38,6 +38,11 @@
#define POSITION_NAME "P"
#define FLAG_NAME "U"
+#define META_BASE_RES "file_base_resolution"
+#define META_VOXEL_SIZE "file_voxel_size"
+#define META_BBOX_MAX "file_bbox_max"
+#define META_BBOX_MIN "file_bbox_min"
+
using namespace std;
namespace Manta {
@@ -388,7 +393,8 @@ int writeObjectsVDB(const string &filename,
int compression,
int precision,
float clip,
- const Grid<Real> *clipGrid)
+ const Grid<Real> *clipGrid,
+ const bool meta)
{
openvdb::initialize();
openvdb::io::File file(filename);
@@ -489,6 +495,16 @@ int writeObjectsVDB(const string &filename,
// Set additional grid attributes, e.g. name, grid class, compression level, etc.
if (vdbGrid) {
setGridOptions<openvdb::GridBase>(vdbGrid, objectName, gClass, voxelSize, precision);
+
+ // Optional metadata: Save additional simulation information per vdb object
+ if (meta) {
+ const Vec3i size = object->getParent()->getGridSize();
+ // The (dense) resolution of this grid
+ vdbGrid->insertMeta(META_BASE_RES,
+ openvdb::Vec3IMetadata(openvdb::Vec3i(size.x, size.y, size.z)));
+ // Length of one voxel side
+ vdbGrid->insertMeta(META_VOXEL_SIZE, openvdb::FloatMetadata(voxelSize));
+ }
}
}
@@ -533,6 +549,44 @@ int writeObjectsVDB(const string &filename,
return 1;
}
+static void clearAll(std::vector<PbClass *> *objects, std::vector<ParticleDataBase *> pdbBuffer)
+{
+ // Clear all data loaded into manta objects (e.g. during IO error)
+ for (std::vector<PbClass *>::iterator iter = objects->begin(); iter != objects->end(); ++iter) {
+ if (GridBase *mantaGrid = dynamic_cast<GridBase *>(*iter)) {
+ if (mantaGrid->getType() & GridBase::TypeInt) {
+ Grid<int> *mantaIntGrid = (Grid<int> *)mantaGrid;
+ mantaIntGrid->clear();
+ }
+ else if (mantaGrid->getType() & GridBase::TypeReal) {
+ Grid<Real> *mantaRealGrid = (Grid<Real> *)mantaGrid;
+ mantaRealGrid->clear();
+ }
+ else if (mantaGrid->getType() & GridBase::TypeVec3) {
+ Grid<Vec3> *mantaVec3Grid = (Grid<Vec3> *)mantaGrid;
+ mantaVec3Grid->clear();
+ }
+ }
+ else if (BasicParticleSystem *mantaPP = dynamic_cast<BasicParticleSystem *>(*iter)) {
+ mantaPP->clear();
+ }
+ }
+ for (ParticleDataBase *pdb : pdbBuffer) {
+ if (pdb->getType() == ParticleDataBase::TypeInt) {
+ ParticleDataImpl<int> *mantaPDataInt = (ParticleDataImpl<int> *)pdb;
+ mantaPDataInt->clear();
+ }
+ else if (pdb->getType() == ParticleDataBase::TypeReal) {
+ ParticleDataImpl<Real> *mantaPDataReal = (ParticleDataImpl<Real> *)pdb;
+ mantaPDataReal->clear();
+ }
+ else if (pdb->getType() == ParticleDataBase::TypeVec3) {
+ ParticleDataImpl<Vec3> *mantaPDataVec3 = (ParticleDataImpl<Vec3> *)pdb;
+ mantaPDataVec3->clear();
+ }
+ }
+}
+
int readObjectsVDB(const string &filename, std::vector<PbClass *> *objects, float worldSize)
{
@@ -561,6 +615,9 @@ int readObjectsVDB(const string &filename, std::vector<PbClass *> *objects, floa
// A buffer to store a handle to pData objects. These will be read alongside a particle system.
std::vector<ParticleDataBase *> pdbBuffer;
+ // Count how many objects could not be read correctly
+ int readFailure = 0;
+
for (std::vector<PbClass *>::iterator iter = objects->begin(); iter != objects->end(); ++iter) {
if (gridsVDB.empty()) {
@@ -568,11 +625,12 @@ int readObjectsVDB(const string &filename, std::vector<PbClass *> *objects, floa
}
// If there is just one grid in this file, load it regardless of name match (to vdb caches per
// grid).
- bool onlyGrid = (gridsVDB.size() == 1);
+ const bool onlyGrid = (gridsVDB.size() == 1);
PbClass *object = dynamic_cast<PbClass *>(*iter);
const Real dx = object->getParent()->getDx();
- const Real voxelSize = worldSize * dx;
+ const Vec3i origRes = object->getParent()->getGridSize();
+ Real voxelSize = worldSize * dx;
// Particle data objects are treated separately - buffered and inserted when reading the
// particle system
@@ -596,6 +654,81 @@ int readObjectsVDB(const string &filename, std::vector<PbClass *> *objects, floa
if (!nameMatch && !onlyGrid) {
continue;
}
+
+ // Metadata: If present in the file, meta data will be parsed into these fields
+ Real metaVoxelSize(0);
+ Vec3i metaRes(0), metaBBoxMax(0), metaBBoxMin(0);
+
+ // Loop to load all meta data that we care about
+ for (openvdb::MetaMap::MetaIterator iter = vdbGrid->beginMeta(); iter != vdbGrid->endMeta();
+ ++iter) {
+ const std::string &name = iter->first;
+ const openvdb::Metadata::Ptr value = iter->second;
+ if (name.compare(META_BASE_RES) == 0) {
+ openvdb::Vec3i tmp = static_cast<openvdb::Vec3IMetadata &>(*value).value();
+ convertFrom(tmp, &metaRes);
+ }
+ else if (name.compare(META_VOXEL_SIZE) == 0) {
+ float tmp = static_cast<openvdb::FloatMetadata &>(*value).value();
+ convertFrom(tmp, &metaVoxelSize);
+
+ voxelSize = metaVoxelSize; // Make sure to update voxel size variable (used in
+ // pointgrid's importVDB())
+ if (worldSize != 1.0)
+ debMsg(
+ "readObjectsVDB: Found voxel size in meta data. worldSize parameter will be "
+ "ignored!",
+ 1);
+ }
+ else if (name.compare(META_BBOX_MAX) == 0) {
+ openvdb::Vec3i tmp = static_cast<openvdb::Vec3IMetadata &>(*value).value();
+ convertFrom(tmp, &metaBBoxMax);
+ }
+ else if (name.compare(META_BBOX_MIN) == 0) {
+ openvdb::Vec3i tmp = static_cast<openvdb::Vec3IMetadata &>(*value).value();
+ convertFrom(tmp, &metaBBoxMin);
+ }
+ else {
+ debMsg("readObjectsVDB: Skipping unknown meta information '" << name << "'", 1);
+ }
+ }
+
+ // Compare metadata with allocated grid setup. This prevents invalid index access.
+ if (notZero(metaRes) && metaRes != origRes) {
+ debMsg("readObjectsVDB Warning: Grid '" << vdbGrid->getName()
+ << "' has not been read. Meta grid res " << metaRes
+ << " vs " << origRes << " current grid size",
+ 1);
+ readFailure++;
+ break;
+ }
+ if (notZero(metaVoxelSize) && metaVoxelSize != voxelSize) {
+ debMsg("readObjectsVDB Warning: Grid '"
+ << vdbGrid->getName() << "' has not been read. Meta voxel size "
+ << metaVoxelSize << " vs " << voxelSize << " current voxel size",
+ 1);
+ readFailure++;
+ break;
+ }
+ if (metaBBoxMax.x > origRes.x || metaBBoxMax.y > origRes.y || metaBBoxMax.z > origRes.z) {
+ debMsg("readObjectsVDB Warning: Grid '"
+ << vdbGrid->getName() << "' has not been read. Vdb bbox max " << metaBBoxMax
+ << " vs " << origRes << " current grid size",
+ 1);
+ readFailure++;
+ break;
+ }
+ const Vec3i origOrigin(0);
+ if (metaBBoxMin.x < origOrigin.x || metaBBoxMin.y < origOrigin.y ||
+ metaBBoxMin.z < origOrigin.z) {
+ debMsg("readObjectsVDB Warning: Grid '"
+ << vdbGrid->getName() << "' has not been read. Vdb bbox min " << metaBBoxMin
+ << " vs " << origOrigin << " current grid origin",
+ 1);
+ readFailure++;
+ break;
+ }
+
if (GridBase *mantaGrid = dynamic_cast<GridBase *>(*iter)) {
if (mantaGrid->getType() & GridBase::TypeInt) {
@@ -655,6 +788,17 @@ int readObjectsVDB(const string &filename, std::vector<PbClass *> *objects, floa
return 0;
}
}
+ // Do not continue loading objects in this loop if there was a read error
+ if (readFailure > 0) {
+ break;
+ }
+ }
+
+ if (readFailure > 0) {
+ // Clear all data that has already been loaded into simulation objects
+ clearAll(objects, pdbBuffer);
+ pdbBuffer.clear();
+ return 0;
}
// Give out a warning if pData items were present but could not be read due to missing particle
@@ -729,7 +873,8 @@ int writeObjectsVDB(const string &filename,
int compression,
int precision,
float clip,
- const Grid<Real> *clipGrid)
+ const Grid<Real> *clipGrid,
+ const bool meta)
{
errMsg("Cannot save to .vdb file. Mantaflow has not been built with OpenVDB support.");
return 0;
diff --git a/extern/mantaflow/preprocessed/fileio/mantaio.cpp b/extern/mantaflow/preprocessed/fileio/mantaio.cpp
index fe29890ec11..ff57ab532e6 100644
--- a/extern/mantaflow/preprocessed/fileio/mantaio.cpp
+++ b/extern/mantaflow/preprocessed/fileio/mantaio.cpp
@@ -85,7 +85,8 @@ int save(const string &name,
bool precisionHalf = true,
int precision = PRECISION_HALF,
float clip = 1e-4,
- const Grid<Real> *clipGrid = nullptr)
+ const Grid<Real> *clipGrid = nullptr,
+ const bool meta = false)
{
if (!precisionHalf) {
@@ -105,7 +106,7 @@ int save(const string &name,
return writeGridsVol(name, &objects);
if (ext == ".vdb")
return writeObjectsVDB(
- name, &objects, worldSize, skipDeletedParts, compression, precision, clip, clipGrid);
+ name, &objects, worldSize, skipDeletedParts, compression, precision, clip, clipGrid, meta);
else if (ext == ".npz")
return writeGridsNumpy(name, &objects);
else if (ext == ".txt")
@@ -134,6 +135,7 @@ static PyObject *_W_1(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
int precision = _args.getOpt<int>("precision", 6, PRECISION_HALF, &_lock);
float clip = _args.getOpt<float>("clip", 7, 1e-4, &_lock);
const Grid<Real> *clipGrid = _args.getPtrOpt<Grid<Real>>("clipGrid", 8, nullptr, &_lock);
+ const bool meta = _args.getOpt<bool>("meta", 9, false, &_lock);
_retval = toPy(save(name,
objects,
worldSize,
@@ -142,7 +144,8 @@ static PyObject *_W_1(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
precisionHalf,
precision,
clip,
- clipGrid));
+ clipGrid,
+ meta));
_args.check();
}
pbFinalizePlugin(parent, "save", !noTiming);
diff --git a/extern/mantaflow/preprocessed/fileio/mantaio.h b/extern/mantaflow/preprocessed/fileio/mantaio.h
index 088d43556e1..26e9319e5e9 100644
--- a/extern/mantaflow/preprocessed/fileio/mantaio.h
+++ b/extern/mantaflow/preprocessed/fileio/mantaio.h
@@ -77,7 +77,8 @@ int writeObjectsVDB(const std::string &filename,
int compression = COMPRESSION_ZIP,
int precision = PRECISION_HALF,
float clip = 1e-4,
- const Grid<Real> *clipGrid = nullptr);
+ const Grid<Real> *clipGrid = nullptr,
+ const bool meta = false);
int readObjectsVDB(const std::string &filename,
std::vector<PbClass *> *objects,
float scale = 1.0);
diff --git a/extern/mantaflow/preprocessed/gitinfo.h b/extern/mantaflow/preprocessed/gitinfo.h
index afc34a00d3d..ddc644db724 100644
--- a/extern/mantaflow/preprocessed/gitinfo.h
+++ b/extern/mantaflow/preprocessed/gitinfo.h
@@ -1,3 +1,3 @@
-#define MANTA_GIT_VERSION "commit e2285cb9bc492987f728123be6cfc1fe11fe73d6"
+#define MANTA_GIT_VERSION "commit 1c86d86496e7f7473c36248d12ef07bf4d9d2840"
diff --git a/extern/mantaflow/preprocessed/grid.cpp b/extern/mantaflow/preprocessed/grid.cpp
index 61672129f37..e0ea3830fae 100644
--- a/extern/mantaflow/preprocessed/grid.cpp
+++ b/extern/mantaflow/preprocessed/grid.cpp
@@ -508,8 +508,7 @@ struct CompMaxVec : public KernelBase {
template<class T> Grid<T> &Grid<T>::copyFrom(const Grid<T> &a, bool copyType)
{
- assertMsg(a.mSize.x == mSize.x && a.mSize.y == mSize.y && a.mSize.z == mSize.z,
- "different grid resolutions " << a.mSize << " vs " << this->mSize);
+ assertMsg(a.mSize == mSize, "different grid resolutions " << a.mSize << " vs " << this->mSize);
memcpy(mData, a.mData, sizeof(T) * mSize.x * mSize.y * mSize.z);
if (copyType)
mType = a.mType; // copy type marker
@@ -3402,8 +3401,7 @@ void PbRegister_markIsolatedFluidCell()
void copyMACData(
const MACGrid &source, MACGrid &target, const FlagGrid &flags, const int flag, const int bnd)
{
- assertMsg(source.getSize().x == target.getSize().x && source.getSize().y == target.getSize().y &&
- source.getSize().z == target.getSize().z,
+ assertMsg(source.getSize() == target.getSize(),
"different grid resolutions " << source.getSize() << " vs " << target.getSize());
// Grid<Real> divGrid(target.getParent());
diff --git a/extern/mantaflow/preprocessed/grid.h b/extern/mantaflow/preprocessed/grid.h
index cf942a19e9a..3d6f8558b8f 100644
--- a/extern/mantaflow/preprocessed/grid.h
+++ b/extern/mantaflow/preprocessed/grid.h
@@ -596,6 +596,7 @@ template<class T> class Grid : public GridBase {
//! set data
inline void set(int i, int j, int k, T &val)
{
+ DEBUG_ONLY(checkIndex(i, j, k));
mData[index(i, j, k)] = val;
}
diff --git a/extern/mantaflow/preprocessed/grid4d.cpp b/extern/mantaflow/preprocessed/grid4d.cpp
index 1a79a835854..72bd3a6fe50 100644
--- a/extern/mantaflow/preprocessed/grid4d.cpp
+++ b/extern/mantaflow/preprocessed/grid4d.cpp
@@ -491,9 +491,7 @@ template<class T> Grid4d<T> &Grid4d<T>::safeDivide(const Grid4d<T> &a)
}
template<class T> Grid4d<T> &Grid4d<T>::copyFrom(const Grid4d<T> &a, bool copyType)
{
- assertMsg(a.mSize.x == mSize.x && a.mSize.y == mSize.y && a.mSize.z == mSize.z &&
- a.mSize.t == mSize.t,
- "different Grid4d resolutions " << a.mSize << " vs " << this->mSize);
+ assertMsg(a.mSize == mSize, "different Grid4d resolutions " << a.mSize << " vs " << this->mSize);
memcpy(mData, a.mData, sizeof(T) * mSize.x * mSize.y * mSize.z * mSize.t);
if (copyType)
mType = a.mType; // copy type marker
diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp
index 1ed2b558938..6c8e45ceeb4 100644
--- a/intern/mantaflow/intern/MANTA_main.cpp
+++ b/intern/mantaflow/intern/MANTA_main.cpp
@@ -1984,7 +1984,9 @@ float MANTA::getTimestep()
bool MANTA::needsRealloc(FluidModifierData *fmd)
{
FluidDomainSettings *fds = fmd->domain;
- return (fds->res[0] != mResX || fds->res[1] != mResY || fds->res[2] != mResZ);
+ return ((fds->res_max[0] - fds->res_min[0]) != mResX ||
+ (fds->res_max[1] - fds->res_min[1]) != mResY ||
+ (fds->res_max[2] - fds->res_min[2]) != mResZ);
}
void MANTA::adaptTimestep()
diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h
index e65310c4bfd..3bf8e66c110 100644
--- a/intern/mantaflow/intern/strings/fluid_script.h
+++ b/intern/mantaflow/intern/strings/fluid_script.h
@@ -711,7 +711,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$, clip=vdbClip_s$ID$, clipGrid=clipGrid)\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, meta=True)\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\
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index 0f8a11a40b2..59248e5f9f8 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -4001,8 +4001,11 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd,
has_config = manta_read_config(fds->fluid, fmd, mesh_frame);
}
- /* Update mesh data from file is faster than via Python (manta_read_mesh()). */
- has_mesh = manta_read_mesh(fds->fluid, fmd, mesh_frame);
+ /* Only load the mesh at the resolution it ways originally simulated at.
+ * The mesh files don't have a header, i.e. the don't store the grid resolution. */
+ if (!manta_needs_realloc(fds->fluid, fmd)) {
+ has_mesh = manta_read_mesh(fds->fluid, fmd, mesh_frame);
+ }
}
/* Read particles cache. */