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:
Diffstat (limited to 'extern/mantaflow/preprocessed/fileio')
-rw-r--r--extern/mantaflow/preprocessed/fileio/iogrids.cpp1524
-rw-r--r--extern/mantaflow/preprocessed/fileio/iomeshes.cpp490
-rw-r--r--extern/mantaflow/preprocessed/fileio/ioparticles.cpp342
-rw-r--r--extern/mantaflow/preprocessed/fileio/mantaio.h81
-rw-r--r--extern/mantaflow/preprocessed/fileio/mantaio.h.reg.cpp13
5 files changed, 2450 insertions, 0 deletions
diff --git a/extern/mantaflow/preprocessed/fileio/iogrids.cpp b/extern/mantaflow/preprocessed/fileio/iogrids.cpp
new file mode 100644
index 00000000000..2f6cdaa6209
--- /dev/null
+++ b/extern/mantaflow/preprocessed/fileio/iogrids.cpp
@@ -0,0 +1,1524 @@
+
+
+// DO NOT EDIT !
+// This file is generated using the MantaFlow preprocessor (prep generate).
+
+/******************************************************************************
+ *
+ * MantaFlow fluid solver framework
+ * Copyright 2011-2016 Tobias Pfaff, Nils Thuerey
+ *
+ * This program is free software, distributed under the terms of the
+ * Apache License, Version 2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Loading and writing grids and meshes to disk
+ *
+ ******************************************************************************/
+
+#include <iostream>
+#include <fstream>
+#include <cstdlib>
+#include <cstring>
+
+#if NO_ZLIB != 1
+extern "C" {
+# include <zlib.h>
+}
+#endif
+
+#if OPENVDB == 1
+# include "openvdb/openvdb.h"
+#endif
+
+#include "cnpy.h"
+#include "mantaio.h"
+#include "grid.h"
+#include "vector4d.h"
+#include "grid4d.h"
+
+using namespace std;
+
+namespace Manta {
+
+static const int STR_LEN_GRID = 252;
+
+//! uni file header, v4
+typedef struct {
+ int dimX, dimY, dimZ; // grid size
+ int gridType, elementType, bytesPerElement; // data type info
+ char info[STR_LEN_GRID]; // mantaflow build information
+ int dimT; // optionally store forth dimension for 4d grids
+ unsigned long long timestamp; // creation time
+} UniHeader;
+
+// note: header v4 only uses 4 bytes of the info string to store the fourth dimension, not needed
+// for pdata
+
+//*****************************************************************************
+// conversion functions for double precision
+// (note - uni files always store single prec. values)
+//*****************************************************************************
+
+#if NO_ZLIB != 1
+template<class GRIDT> void gridConvertWrite(gzFile &gzf, GRIDT &grid, void *ptr, UniHeader &head)
+{
+ errMsg("gridConvertWrite: unknown type, not yet supported");
+}
+
+template<> void gridConvertWrite(gzFile &gzf, Grid<int> &grid, void *ptr, UniHeader &head)
+{
+ gzwrite(gzf, &head, sizeof(UniHeader));
+ gzwrite(gzf, &grid[0], sizeof(int) * head.dimX * head.dimY * head.dimZ);
+}
+template<> void gridConvertWrite(gzFile &gzf, Grid<double> &grid, void *ptr, UniHeader &head)
+{
+ head.bytesPerElement = sizeof(float);
+ gzwrite(gzf, &head, sizeof(UniHeader));
+ float *ptrf = (float *)ptr;
+ for (int i = 0; i < grid.getSizeX() * grid.getSizeY() * grid.getSizeZ(); ++i, ++ptrf) {
+ *ptrf = (float)grid[i];
+ }
+ gzwrite(gzf, ptr, sizeof(float) * head.dimX * head.dimY * head.dimZ);
+}
+template<>
+void gridConvertWrite(gzFile &gzf, Grid<Vector3D<double>> &grid, void *ptr, UniHeader &head)
+{
+ head.bytesPerElement = sizeof(Vector3D<float>);
+ gzwrite(gzf, &head, sizeof(UniHeader));
+ float *ptrf = (float *)ptr;
+ for (int i = 0; i < grid.getSizeX() * grid.getSizeY() * grid.getSizeZ(); ++i) {
+ for (int c = 0; c < 3; ++c) {
+ *ptrf = (float)grid[i][c];
+ ptrf++;
+ }
+ }
+ gzwrite(gzf, ptr, sizeof(Vector3D<float>) * head.dimX * head.dimY * head.dimZ);
+}
+
+template<> void gridConvertWrite(gzFile &gzf, Grid4d<int> &grid, void *ptr, UniHeader &head)
+{
+ gzwrite(gzf, &head, sizeof(UniHeader));
+ gzwrite(gzf, &grid[0], sizeof(int) * head.dimX * head.dimY * head.dimZ * head.dimT);
+}
+template<> void gridConvertWrite(gzFile &gzf, Grid4d<double> &grid, void *ptr, UniHeader &head)
+{
+ head.bytesPerElement = sizeof(float);
+ gzwrite(gzf, &head, sizeof(UniHeader));
+ float *ptrf = (float *)ptr;
+ IndexInt s = grid.getStrideT() * grid.getSizeT();
+ for (IndexInt i = 0; i < s; ++i, ++ptrf) {
+ *ptrf = (float)grid[i];
+ }
+ gzwrite(gzf, ptr, sizeof(float) * s);
+}
+template<>
+void gridConvertWrite(gzFile &gzf, Grid4d<Vector3D<double>> &grid, void *ptr, UniHeader &head)
+{
+ head.bytesPerElement = sizeof(Vector3D<float>);
+ gzwrite(gzf, &head, sizeof(UniHeader));
+ float *ptrf = (float *)ptr;
+ IndexInt s = grid.getStrideT() * grid.getSizeT();
+ for (IndexInt i = 0; i < s; ++i) {
+ for (int c = 0; c < 3; ++c) {
+ *ptrf = (float)grid[i][c];
+ ptrf++;
+ }
+ }
+ gzwrite(gzf, ptr, sizeof(Vector3D<float>) * s);
+}
+template<>
+void gridConvertWrite(gzFile &gzf, Grid4d<Vector4D<double>> &grid, void *ptr, UniHeader &head)
+{
+ head.bytesPerElement = sizeof(Vector4D<float>);
+ gzwrite(gzf, &head, sizeof(UniHeader));
+ float *ptrf = (float *)ptr;
+ IndexInt s = grid.getStrideT() * grid.getSizeT();
+ for (IndexInt i = 0; i < s; ++i) {
+ for (int c = 0; c < 4; ++c) {
+ *ptrf = (float)grid[i][c];
+ ptrf++;
+ }
+ }
+ gzwrite(gzf, ptr, sizeof(Vector4D<float>) * s);
+}
+
+template<class T> void gridReadConvert(gzFile &gzf, Grid<T> &grid, void *ptr, int bytesPerElement)
+{
+ errMsg("gridReadConvert: unknown type, not yet supported");
+}
+
+template<> void gridReadConvert<int>(gzFile &gzf, Grid<int> &grid, void *ptr, int bytesPerElement)
+{
+ gzread(gzf, ptr, sizeof(int) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ());
+ assertMsg(bytesPerElement == sizeof(int),
+ "grid element size doesn't match " << bytesPerElement << " vs " << sizeof(int));
+ // easy, nothing to do for ints
+ memcpy(&(grid[0]), ptr, sizeof(int) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ());
+}
+
+template<>
+void gridReadConvert<double>(gzFile &gzf, Grid<double> &grid, void *ptr, int bytesPerElement)
+{
+ gzread(gzf, ptr, sizeof(float) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ());
+ assertMsg(bytesPerElement == sizeof(float),
+ "grid element size doesn't match " << bytesPerElement << " vs " << sizeof(float));
+ float *ptrf = (float *)ptr;
+ for (int i = 0; i < grid.getSizeX() * grid.getSizeY() * grid.getSizeZ(); ++i, ++ptrf) {
+ grid[i] = (double)(*ptrf);
+ }
+}
+
+template<>
+void gridReadConvert<Vec3>(gzFile &gzf, Grid<Vec3> &grid, void *ptr, int bytesPerElement)
+{
+ gzread(gzf, ptr, sizeof(Vector3D<float>) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ());
+ assertMsg(bytesPerElement == sizeof(Vector3D<float>),
+ "grid element size doesn't match " << bytesPerElement << " vs "
+ << sizeof(Vector3D<float>));
+ float *ptrf = (float *)ptr;
+ for (int i = 0; i < grid.getSizeX() * grid.getSizeY() * grid.getSizeZ(); ++i) {
+ Vec3 v;
+ for (int c = 0; c < 3; ++c) {
+ v[c] = double(*ptrf);
+ ptrf++;
+ }
+ grid[i] = v;
+ }
+}
+
+template<class T>
+void gridReadConvert4d(gzFile &gzf, Grid4d<T> &grid, void *ptr, int bytesPerElement, int t)
+{
+ errMsg("gridReadConvert4d: unknown type, not yet supported");
+}
+
+template<>
+void gridReadConvert4d<int>(gzFile &gzf, Grid4d<int> &grid, void *ptr, int bytesPerElement, int t)
+{
+ gzread(gzf, ptr, sizeof(int) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ());
+ assertMsg(bytesPerElement == sizeof(int),
+ "grid element size doesn't match " << bytesPerElement << " vs " << sizeof(int));
+ // nothing to do for ints
+ memcpy(&(grid[grid.getSizeX() * grid.getSizeY() * grid.getSizeZ() * t]),
+ ptr,
+ sizeof(int) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ());
+}
+
+template<>
+void gridReadConvert4d<double>(
+ gzFile &gzf, Grid4d<double> &grid, void *ptr, int bytesPerElement, int t)
+{
+ assertMsg(bytesPerElement == sizeof(float),
+ "grid element size doesn't match " << bytesPerElement << " vs " << sizeof(float));
+
+ float *ptrf = (float *)ptr;
+ gzread(gzf, ptr, sizeof(float) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ());
+ for (IndexInt i = 0; i < grid.getSizeX() * grid.getSizeY() * grid.getSizeZ(); ++i, ++ptrf) {
+ grid[grid.getSizeX() * grid.getSizeY() * grid.getSizeZ() * t + i] = (double)(*ptrf);
+ }
+}
+
+template<>
+void gridReadConvert4d<Vec3>(
+ gzFile &gzf, Grid4d<Vec3> &grid, void *ptr, int bytesPerElement, int t)
+{
+ assertMsg(bytesPerElement == sizeof(Vector3D<float>),
+ "grid element size doesn't match " << bytesPerElement << " vs " << sizeof(float));
+
+ gzread(gzf, ptr, sizeof(Vector3D<float>) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ());
+ float *ptrf = (float *)ptr;
+ for (IndexInt i = 0; i < grid.getSizeX() * grid.getSizeY() * grid.getSizeZ(); ++i) {
+ Vec3 v;
+ for (int c = 0; c < 3; ++c) {
+ v[c] = double(*ptrf);
+ ptrf++;
+ }
+ grid[grid.getSizeX() * grid.getSizeY() * grid.getSizeZ() * t + i] = v;
+ }
+}
+
+template<>
+void gridReadConvert4d<Vec4>(
+ gzFile &gzf, Grid4d<Vec4> &grid, void *ptr, int bytesPerElement, int t)
+{
+ assertMsg(bytesPerElement == sizeof(Vector4D<float>),
+ "grid element size doesn't match " << bytesPerElement << " vs " << sizeof(float));
+
+ gzread(gzf, ptr, sizeof(Vector4D<float>) * grid.getSizeX() * grid.getSizeY() * grid.getSizeZ());
+ float *ptrf = (float *)ptr;
+ for (IndexInt i = 0; i < grid.getSizeX() * grid.getSizeY() * grid.getSizeZ(); ++i) {
+ Vec4 v;
+ for (int c = 0; c < 4; ++c) {
+ v[c] = double(*ptrf);
+ ptrf++;
+ }
+ grid[grid.getSizeX() * grid.getSizeY() * grid.getSizeZ() * t + i] = v;
+ }
+}
+
+// make sure compatible grid types dont lead to errors...
+static int unifyGridType(int type)
+{
+ // real <> levelset
+ if (type & GridBase::TypeReal)
+ type |= GridBase::TypeLevelset;
+ if (type & GridBase::TypeLevelset)
+ type |= GridBase::TypeReal;
+ // vec3 <> mac
+ if (type & GridBase::TypeVec3)
+ type |= GridBase::TypeMAC;
+ if (type & GridBase::TypeMAC)
+ type |= GridBase::TypeVec3;
+ return type;
+}
+
+#endif // NO_ZLIB!=1
+
+//*****************************************************************************
+// grid data
+//*****************************************************************************
+
+template<class T> void writeGridTxt(const string &name, Grid<T> *grid)
+{
+ debMsg("writing grid " << grid->getName() << " to text file " << name, 1);
+
+ ofstream ofs(name.c_str());
+ if (!ofs.good())
+ errMsg("writeGridTxt: can't open file " << name);
+ FOR_IJK(*grid)
+ {
+ ofs << Vec3i(i, j, k) << " = " << (*grid)(i, j, k) << "\n";
+ }
+ ofs.close();
+}
+
+template<class T> void writeGridRaw(const string &name, Grid<T> *grid)
+{
+ debMsg("writing grid " << grid->getName() << " to raw file " << name, 1);
+
+#if NO_ZLIB != 1
+ gzFile gzf = gzopen(name.c_str(), "wb1"); // do some compression
+ if (!gzf)
+ errMsg("writeGridRaw: can't open file " << name);
+ gzwrite(gzf, &((*grid)[0]), sizeof(T) * grid->getSizeX() * grid->getSizeY() * grid->getSizeZ());
+ gzclose(gzf);
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+}
+
+template<class T> void readGridRaw(const string &name, Grid<T> *grid)
+{
+ debMsg("reading grid " << grid->getName() << " from raw file " << name, 1);
+
+#if NO_ZLIB != 1
+ gzFile gzf = gzopen(name.c_str(), "rb");
+ if (!gzf)
+ errMsg("readGridRaw: can't open file " << name);
+
+ IndexInt bytes = sizeof(T) * grid->getSizeX() * grid->getSizeY() * grid->getSizeZ();
+ IndexInt readBytes = gzread(gzf, &((*grid)[0]), bytes);
+ assertMsg(bytes == readBytes,
+ "can't read raw file, stream length does not match, " << bytes << " vs " << readBytes);
+ gzclose(gzf);
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+}
+
+//! legacy headers for reading old files
+typedef struct {
+ int dimX, dimY, dimZ;
+ int frames, elements, elementType, bytesPerElement, bytesPerFrame;
+} UniLegacyHeader;
+
+typedef struct {
+ int dimX, dimY, dimZ;
+ int gridType, elementType, bytesPerElement;
+} UniLegacyHeader2;
+
+typedef struct {
+ int dimX, dimY, dimZ;
+ int gridType, elementType, bytesPerElement;
+ char info[256];
+ unsigned long long timestamp;
+} UniLegacyHeader3;
+
+//! for auto-init & check of results of test runs , optionally returns info string of header
+void getUniFileSize(const string &name, int &x, int &y, int &z, int *t, std::string *info)
+{
+ x = y = z = 0;
+#if NO_ZLIB != 1
+ gzFile gzf = gzopen(name.c_str(), "rb");
+ if (gzf) {
+ char ID[5] = {0, 0, 0, 0, 0};
+ gzread(gzf, ID, 4);
+
+ // v3
+ if ((!strcmp(ID, "MNT2")) || (!strcmp(ID, "M4T2"))) {
+ UniLegacyHeader3 head;
+ assertMsg(gzread(gzf, &head, sizeof(UniLegacyHeader3)) == sizeof(UniLegacyHeader3),
+ "can't read file, no header present");
+ x = head.dimX;
+ y = head.dimY;
+ z = head.dimZ;
+
+ // optionally , read fourth dim
+ if ((!strcmp(ID, "M4T2")) && t) {
+ int dimT = 0;
+ gzread(gzf, &dimT, sizeof(int));
+ (*t) = dimT;
+ }
+ }
+
+ // v4
+ if ((!strcmp(ID, "MNT3")) || (!strcmp(ID, "M4T3"))) {
+ UniHeader head;
+ assertMsg(gzread(gzf, &head, sizeof(UniHeader)) == sizeof(UniHeader),
+ "can't read file, no header present");
+ x = head.dimX;
+ y = head.dimY;
+ z = head.dimZ;
+ if (t)
+ (*t) = head.dimT;
+ }
+
+ gzclose(gzf);
+ }
+#endif
+ if (info) {
+ std::ostringstream out;
+ out << x << "," << y << "," << z;
+ if (t && (*t) > 0)
+ out << "," << (*t);
+ *info = out.str();
+ }
+}
+Vec3 getUniFileSize(const string &name)
+{
+ int x, y, z;
+ getUniFileSize(name, x, y, z);
+ return Vec3(Real(x), Real(y), Real(z));
+}
+static PyObject *_W_0(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
+{
+ try {
+ PbArgs _args(_linargs, _kwds);
+ FluidSolver *parent = _args.obtainParent();
+ bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
+ pbPreparePlugin(parent, "getUniFileSize", !noTiming);
+ PyObject *_retval = 0;
+ {
+ ArgLocker _lock;
+ const string &name = _args.get<string>("name", 0, &_lock);
+ _retval = toPy(getUniFileSize(name));
+ _args.check();
+ }
+ pbFinalizePlugin(parent, "getUniFileSize", !noTiming);
+ return _retval;
+ }
+ catch (std::exception &e) {
+ pbSetError("getUniFileSize", e.what());
+ return 0;
+ }
+}
+static const Pb::Register _RP_getUniFileSize("", "getUniFileSize", _W_0);
+extern "C" {
+void PbRegister_getUniFileSize()
+{
+ KEEP_UNUSED(_RP_getUniFileSize);
+}
+}
+
+//! for test run debugging
+void printUniFileInfoString(const string &name)
+{
+ std::string info("<file not found>");
+ int x = -1, y = -1, z = -1, t = -1;
+ // use getUniFileSize to parse the different headers
+ getUniFileSize(name, x, y, z, &t, &info);
+ debMsg("File '" << name << "' info: " << info, 1);
+}
+static PyObject *_W_1(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
+{
+ try {
+ PbArgs _args(_linargs, _kwds);
+ FluidSolver *parent = _args.obtainParent();
+ bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
+ pbPreparePlugin(parent, "printUniFileInfoString", !noTiming);
+ PyObject *_retval = 0;
+ {
+ ArgLocker _lock;
+ const string &name = _args.get<string>("name", 0, &_lock);
+ _retval = getPyNone();
+ printUniFileInfoString(name);
+ _args.check();
+ }
+ pbFinalizePlugin(parent, "printUniFileInfoString", !noTiming);
+ return _retval;
+ }
+ catch (std::exception &e) {
+ pbSetError("printUniFileInfoString", e.what());
+ return 0;
+ }
+}
+static const Pb::Register _RP_printUniFileInfoString("", "printUniFileInfoString", _W_1);
+extern "C" {
+void PbRegister_printUniFileInfoString()
+{
+ KEEP_UNUSED(_RP_printUniFileInfoString);
+}
+}
+
+// actual read/write functions
+
+template<class T> void writeGridUni(const string &name, Grid<T> *grid)
+{
+ debMsg("Writing grid " << grid->getName() << " to uni file " << name, 1);
+
+#if NO_ZLIB != 1
+ char ID[5] = "MNT3";
+ UniHeader head;
+ head.dimX = grid->getSizeX();
+ head.dimY = grid->getSizeY();
+ head.dimZ = grid->getSizeZ();
+ head.dimT = 0;
+ head.gridType = grid->getType();
+ head.bytesPerElement = sizeof(T);
+ snprintf(head.info, STR_LEN_GRID, "%s", buildInfoString().c_str());
+ MuTime stamp;
+ head.timestamp = stamp.time;
+
+ if (grid->getType() & GridBase::TypeInt)
+ head.elementType = 0;
+ else if (grid->getType() & GridBase::TypeReal)
+ head.elementType = 1;
+ else if (grid->getType() & GridBase::TypeVec3)
+ head.elementType = 2;
+ else
+ errMsg("writeGridUni: unknown element type");
+
+ gzFile gzf = gzopen(name.c_str(), "wb1"); // do some compression
+ if (!gzf)
+ errMsg("writeGridUni: can't open file " << name);
+
+ gzwrite(gzf, ID, 4);
+# if FLOATINGPOINT_PRECISION != 1
+ // always write float values, even if compiled with double precision...
+ Grid<T> temp(grid->getParent());
+ // "misuse" temp grid as storage for floating point values (we have double, so it will always
+ // fit)
+ gridConvertWrite(gzf, *grid, &(temp[0]), head);
+# else
+ void *ptr = &((*grid)[0]);
+ gzwrite(gzf, &head, sizeof(UniHeader));
+ gzwrite(gzf, ptr, sizeof(T) * head.dimX * head.dimY * head.dimZ);
+# endif
+ gzclose(gzf);
+
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+};
+
+template<class T> void readGridUni(const string &name, Grid<T> *grid)
+{
+ debMsg("Reading grid " << grid->getName() << " from uni file " << name, 1);
+
+#if NO_ZLIB != 1
+ gzFile gzf = gzopen(name.c_str(), "rb");
+ if (!gzf)
+ errMsg("readGridUni: can't open file " << name);
+
+ char ID[5] = {0, 0, 0, 0, 0};
+ gzread(gzf, ID, 4);
+
+ if (!strcmp(ID, "DDF2")) {
+ // legacy file format
+ UniLegacyHeader head;
+ assertMsg(gzread(gzf, &head, sizeof(UniLegacyHeader)) == sizeof(UniLegacyHeader),
+ "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");
+ assertMsg(head.bytesPerElement * head.elements == sizeof(T), "grid type doesn't match");
+ // skip flags
+ int numEl = head.dimX * head.dimY * head.dimZ;
+ gzseek(gzf, numEl, SEEK_CUR);
+ // actual grid read
+ gzread(gzf, &((*grid)[0]), sizeof(T) * numEl);
+ }
+ else if (!strcmp(ID, "MNT1")) {
+ // legacy file format 2
+ UniLegacyHeader2 head;
+ assertMsg(gzread(gzf, &head, sizeof(UniLegacyHeader2)) == sizeof(UniLegacyHeader2),
+ "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());
+ assertMsg(head.gridType == grid->getType(),
+ "grid type doesn't match " << head.gridType << " vs " << grid->getType());
+ assertMsg(head.bytesPerElement == sizeof(T),
+ "grid element size doesn't match " << head.bytesPerElement << " vs " << sizeof(T));
+ gzread(gzf, &((*grid)[0]), sizeof(T) * head.dimX * head.dimY * head.dimZ);
+ }
+ else if (!strcmp(ID, "MNT2")) {
+ // a bit ugly, almost identical to MNT3
+ UniLegacyHeader3 head;
+ assertMsg(gzread(gzf, &head, sizeof(UniLegacyHeader3)) == sizeof(UniLegacyHeader3),
+ "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());
+ assertMsg(unifyGridType(head.gridType) == unifyGridType(grid->getType()),
+ "grid type doesn't match " << head.gridType << " vs " << grid->getType());
+# if FLOATINGPOINT_PRECISION != 1
+ Grid<T> temp(grid->getParent());
+ void *ptr = &(temp[0]);
+ gridReadConvert<T>(gzf, *grid, ptr, head.bytesPerElement);
+# else
+ assertMsg(head.bytesPerElement == sizeof(T),
+ "grid element size doesn't match " << head.bytesPerElement << " vs " << sizeof(T));
+ gzread(gzf, &((*grid)[0]), sizeof(T) * head.dimX * head.dimY * head.dimZ);
+# endif
+ }
+ else if (!strcmp(ID, "MNT3")) {
+ // 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());
+ assertMsg(unifyGridType(head.gridType) == unifyGridType(grid->getType()),
+ "grid type doesn't match " << head.gridType << " vs " << grid->getType());
+# if FLOATINGPOINT_PRECISION != 1
+ // convert float to double
+ Grid<T> temp(grid->getParent());
+ void *ptr = &(temp[0]);
+ gridReadConvert<T>(gzf, *grid, ptr, head.bytesPerElement);
+# else
+ assertMsg(head.bytesPerElement == sizeof(T),
+ "grid element size doesn't match " << head.bytesPerElement << " vs " << sizeof(T));
+ gzread(gzf, &((*grid)[0]), sizeof(T) * head.dimX * head.dimY * head.dimZ);
+# endif
+ }
+ else {
+ errMsg("readGridUni: Unknown header '" << ID << "' ");
+ }
+ gzclose(gzf);
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+};
+
+template<class T> void writeGridVol(const string &name, Grid<T> *grid)
+{
+ debMsg("writing grid " << grid->getName() << " to vol file " << name, 1);
+ errMsg("writeGridVol: Type not yet supported!");
+}
+
+struct volHeader {
+ char ID[3];
+ char version;
+ int encoding;
+ int dimX, dimY, dimZ;
+ int channels;
+ Vec3 bboxMin, bboxMax;
+};
+
+template<> void writeGridVol<Real>(const string &name, Grid<Real> *grid)
+{
+ debMsg("writing real grid " << grid->getName() << " to vol file " << name, 1);
+
+ volHeader header;
+ header.ID[0] = 'V';
+ header.ID[1] = 'O';
+ header.ID[2] = 'L';
+ header.version = 3;
+ header.encoding = 1; // float32 precision
+ header.dimX = grid->getSizeX();
+ header.dimY = grid->getSizeY();
+ header.dimZ = grid->getSizeZ();
+ header.channels = 1; // only 1 channel
+ header.bboxMin = Vec3(-0.5);
+ header.bboxMax = Vec3(0.5);
+
+ FILE *fp = fopen(name.c_str(), "wb");
+ if (fp == NULL) {
+ errMsg("writeGridVol: Cannot open '" << name << "'");
+ return;
+ }
+
+ fwrite(&header, sizeof(volHeader), 1, fp);
+
+#if FLOATINGPOINT_PRECISION == 1
+ // for float, write one big chunk
+ fwrite(&(*grid)[0], sizeof(float), grid->getSizeX() * grid->getSizeY() * grid->getSizeZ(), fp);
+#else
+ // explicitly convert each entry to float - we might have double precision in mantaflow
+ FOR_IDX(*grid)
+ {
+ float value = (*grid)[idx];
+ fwrite(&value, sizeof(float), 1, fp);
+ }
+#endif
+
+ fclose(fp);
+};
+
+template<class T> void readGridVol(const string &name, Grid<T> *grid)
+{
+ debMsg("writing grid " << grid->getName() << " to vol file " << name, 1);
+ errMsg("readGridVol: Type not yet supported!");
+}
+
+template<> void readGridVol<Real>(const string &name, Grid<Real> *grid)
+{
+ debMsg("reading real grid " << grid->getName() << " from vol file " << name, 1);
+
+ volHeader header;
+ FILE *fp = fopen(name.c_str(), "rb");
+ if (fp == NULL) {
+ errMsg("readGridVol: Cannot open '" << name << "'");
+ return;
+ }
+
+ // note, only very basic file format checks here!
+ assertMsg(fread(&header, 1, sizeof(volHeader), fp) == sizeof(volHeader),
+ "can't read file, no header present");
+ if (header.dimX != grid->getSizeX() || header.dimY != grid->getSizeY() ||
+ header.dimZ != grid->getSizeZ())
+ errMsg("grid dim doesn't match, " << Vec3(header.dimX, header.dimY, header.dimZ) << " vs "
+ << grid->getSize());
+#if FLOATINGPOINT_PRECISION != 1
+ errMsg("readGridVol: Double precision not yet supported");
+#else
+ const unsigned int s = sizeof(float) * header.dimX * header.dimY * header.dimZ;
+ assertMsg(fread(&((*grid)[0]), 1, s, fp) == s, "can't read file, no / not enough data");
+#endif
+
+ fclose(fp);
+};
+
+// 4d grids IO
+
+template<class T> void writeGrid4dUni(const string &name, Grid4d<T> *grid)
+{
+ debMsg("writing grid4d " << grid->getName() << " to uni file " << name, 1);
+
+#if NO_ZLIB != 1
+ char ID[5] = "M4T3";
+ UniHeader head;
+ head.dimX = grid->getSizeX();
+ head.dimY = grid->getSizeY();
+ head.dimZ = grid->getSizeZ();
+ head.dimT = grid->getSizeT();
+ head.gridType = grid->getType();
+ head.bytesPerElement = sizeof(T);
+ snprintf(head.info, STR_LEN_GRID, "%s", buildInfoString().c_str());
+ MuTime stamp;
+ stamp.get();
+ head.timestamp = stamp.time;
+
+ if (grid->getType() & Grid4dBase::TypeInt)
+ head.elementType = 0;
+ else if (grid->getType() & Grid4dBase::TypeReal)
+ head.elementType = 1;
+ else if (grid->getType() & Grid4dBase::TypeVec3)
+ head.elementType = 2;
+ else if (grid->getType() & Grid4dBase::TypeVec4)
+ head.elementType = 2;
+ else
+ errMsg("writeGrid4dUni: unknown element type");
+
+ gzFile gzf = gzopen(name.c_str(), "wb1"); // do some compression
+ if (!gzf)
+ errMsg("writeGrid4dUni: can't open file " << name);
+
+ gzwrite(gzf, ID, 4);
+# if FLOATINGPOINT_PRECISION != 1
+ Grid4d<T> temp(grid->getParent());
+ gridConvertWrite<Grid4d<T>>(gzf, *grid, &(temp[0]), head);
+# else
+ gzwrite(gzf, &head, sizeof(UniHeader));
+
+ // can be too large - write in chunks
+ for (int t = 0; t < head.dimT; ++t) {
+ void *ptr = &((*grid)[head.dimX * head.dimY * head.dimZ * t]);
+ gzwrite(gzf, ptr, sizeof(T) * head.dimX * head.dimY * head.dimZ * 1);
+ }
+# endif
+ gzclose(gzf);
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+};
+
+//! note, reading 4d uni grids is slightly more complicated than 3d ones
+//! as it optionally supports sliced reading
+template<class T>
+void readGrid4dUni(
+ const string &name, Grid4d<T> *grid, int readTslice, Grid4d<T> *slice, void **fileHandle)
+{
+ if (grid)
+ debMsg("reading grid " << grid->getName() << " from uni file " << name, 1);
+ if (slice)
+ debMsg("reading slice " << slice->getName() << ",t=" << readTslice << " from uni file "
+ << name,
+ 1);
+
+#if NO_ZLIB != 1
+ gzFile gzf = NULL;
+ char ID[5] = {0, 0, 0, 0, 0};
+
+ // optionally - reuse file handle, if valid one is passed in fileHandle pointer...
+ if ((!fileHandle) || (fileHandle && (*fileHandle == NULL))) {
+ gzf = gzopen(name.c_str(), "rb");
+ if (!gzf)
+ errMsg("readGrid4dUni: can't open file " << name);
+
+ gzread(gzf, ID, 4);
+ if (fileHandle) {
+ *fileHandle = gzf;
+ }
+ }
+ else {
+ // optimized read - reduced sanity checks
+ gzf = (gzFile)(*fileHandle);
+ void *ptr = &((*slice)[0]);
+ gzread(gzf, ptr, sizeof(T) * slice->getStrideT() * 1); // quick and dirty...
+ return;
+ }
+
+ if ((!strcmp(ID, "M4T2")) || (!strcmp(ID, "M4T3"))) {
+ int headerSize = -1;
+
+ // current file format
+ UniHeader head;
+ if (!strcmp(ID, "M4T3")) {
+ headerSize = sizeof(UniHeader);
+ assertMsg(gzread(gzf, &head, sizeof(UniHeader)) == sizeof(UniHeader),
+ "can't read file, no 4d header present");
+ if (FLOATINGPOINT_PRECISION == 1)
+ assertMsg(head.bytesPerElement == sizeof(T),
+ "4d grid element size doesn't match " << head.bytesPerElement << " vs "
+ << sizeof(T));
+ }
+ // old header
+ if (!strcmp(ID, "M4T2")) {
+ UniLegacyHeader3 lhead;
+ headerSize = sizeof(UniLegacyHeader3) + sizeof(int);
+ assertMsg(gzread(gzf, &lhead, sizeof(UniLegacyHeader3)) == sizeof(UniLegacyHeader3),
+ "can't read file, no 4dl header present");
+ if (FLOATINGPOINT_PRECISION == 1)
+ assertMsg(lhead.bytesPerElement == sizeof(T),
+ "4d grid element size doesn't match " << lhead.bytesPerElement << " vs "
+ << sizeof(T));
+
+ int fourthDim = 0;
+ gzread(gzf, &fourthDim, sizeof(fourthDim));
+
+ head.dimX = lhead.dimX;
+ head.dimY = lhead.dimY;
+ head.dimZ = lhead.dimZ;
+ head.dimT = fourthDim;
+ head.gridType = lhead.gridType;
+ }
+
+ if (readTslice < 0) {
+ 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());
+ assertMsg(unifyGridType(head.gridType) == unifyGridType(grid->getType()),
+ "grid type doesn't match " << head.gridType << " vs " << grid->getType());
+
+ // read full 4d grid
+ assertMsg(head.dimT == grid->getSizeT(),
+ "grid dim4 doesn't match, " << head.dimT << " vs " << grid->getSize());
+
+ // can be too large - read in chunks
+# if FLOATINGPOINT_PRECISION != 1
+ Grid4d<T> temp(grid->getParent());
+ void *ptr = &(temp[0]);
+ for (int t = 0; t < head.dimT; ++t) {
+ gridReadConvert4d<T>(gzf, *grid, ptr, head.bytesPerElement, t);
+ }
+# else
+ for (int t = 0; t < head.dimT; ++t) {
+ void *ptr = &((*grid)[head.dimX * head.dimY * head.dimZ * t]);
+ gzread(gzf, ptr, sizeof(T) * head.dimX * head.dimY * head.dimZ * 1);
+ }
+# endif
+ }
+ else {
+ // read chosen slice only
+ assertMsg(head.dimX == slice->getSizeX() && head.dimY == slice->getSizeY() &&
+ head.dimZ == slice->getSizeZ(),
+ "grid dim doesn't match, " << Vec3(head.dimX, head.dimY, head.dimZ) << " vs "
+ << slice->getSize());
+ assertMsg(unifyGridType(head.gridType) == unifyGridType(slice->getType()),
+ "grid type doesn't match " << head.gridType << " vs " << slice->getType());
+
+# if FLOATINGPOINT_PRECISION != 1
+ errMsg("readGrid4dUni: NYI (2)"); // slice read not yet supported for double
+# else
+ assertMsg(slice, "No 3d slice grid data given");
+ assertMsg(readTslice < head.dimT,
+ "grid dim4 slice too large " << readTslice << " vs " << head.dimT);
+ void *ptr = &((*slice)[0]);
+ gzseek(gzf,
+ sizeof(T) * head.dimX * head.dimY * head.dimZ * readTslice + headerSize + 4,
+ SEEK_SET);
+ gzread(gzf, ptr, sizeof(T) * head.dimX * head.dimY * head.dimZ * 1);
+# endif
+ }
+ }
+ else {
+ debMsg("Unknown header!", 1);
+ }
+
+ if (!fileHandle) {
+ gzclose(gzf);
+ }
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+};
+void readGrid4dUniCleanup(void **fileHandle)
+{
+ gzFile gzf = NULL;
+ if (fileHandle) {
+ gzf = (gzFile)(*fileHandle);
+ gzclose(gzf);
+ *fileHandle = NULL;
+ }
+}
+
+template<class T> void writeGrid4dRaw(const string &name, Grid4d<T> *grid)
+{
+ debMsg("writing grid4d " << grid->getName() << " to raw file " << name, 1);
+
+#if NO_ZLIB != 1
+ gzFile gzf = gzopen(name.c_str(), "wb1"); // do some compression
+ if (!gzf)
+ errMsg("writeGrid4dRaw: can't open file " << name);
+ gzwrite(gzf,
+ &((*grid)[0]),
+ sizeof(T) * grid->getSizeX() * grid->getSizeY() * grid->getSizeZ() * grid->getSizeT());
+ gzclose(gzf);
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+}
+
+template<class T> void readGrid4dRaw(const string &name, Grid4d<T> *grid)
+{
+ debMsg("reading grid4d " << grid->getName() << " from raw file " << name, 1);
+
+#if NO_ZLIB != 1
+ gzFile gzf = gzopen(name.c_str(), "rb");
+ if (!gzf)
+ errMsg("readGrid4dRaw: can't open file " << name);
+
+ IndexInt bytes = sizeof(T) * grid->getSizeX() * grid->getSizeY() * grid->getSizeZ() *
+ grid->getSizeT();
+ IndexInt readBytes = gzread(gzf, &((*grid)[0]), bytes);
+ assertMsg(bytes == readBytes,
+ "can't read raw file, stream length does not match, " << bytes << " vs " << readBytes);
+ gzclose(gzf);
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+}
+
+//*****************************************************************************
+// optional openvdb export
+
+#if OPENVDB == 1
+
+template<class T> void writeGridVDB(const string &name, Grid<T> *grid)
+{
+ debMsg("Writing grid " << grid->getName() << " to vdb file " << name << " not yet supported!",
+ 1);
+}
+
+template<class T> void readGridVDB(const string &name, Grid<T> *grid)
+{
+ debMsg("Reading grid " << grid->getName() << " from vdb file " << name << " not yet supported!",
+ 1);
+}
+
+template<> void writeGridVDB(const string &name, Grid<Real> *grid)
+{
+ debMsg("Writing real grid " << grid->getName() << " to vdb file " << name, 1);
+
+ // Create an empty floating-point grid with background value 0.
+ openvdb::initialize();
+ openvdb::FloatGrid::Ptr gridVDB = openvdb::FloatGrid::create();
+ gridVDB->setTransform(
+ openvdb::math::Transform::createLinearTransform(1. / grid->getSizeX())); // voxel size
+
+ // Get an accessor for coordinate-based access to voxels.
+ openvdb::FloatGrid::Accessor accessor = gridVDB->getAccessor();
+
+ // Identify the grid as a level set.
+ gridVDB->setGridClass(openvdb::GRID_FOG_VOLUME);
+
+ // Name the grid "density".
+ gridVDB->setName(grid->getName());
+
+ openvdb::io::File file(name);
+
+ FOR_IJK(*grid)
+ {
+ openvdb::Coord xyz(i, j, k);
+ accessor.setValue(xyz, (*grid)(i, j, k));
+ }
+
+ // Add the grid pointer to a container.
+ openvdb::GridPtrVec gridsVDB;
+ gridsVDB.push_back(gridVDB);
+
+ // Write out the contents of the container.
+ file.write(gridsVDB);
+ file.close();
+};
+
+template<> void readGridVDB(const string &name, Grid<Real> *grid)
+{
+ debMsg("Reading real grid " << grid->getName() << " from vdb file " << name, 1);
+
+ openvdb::initialize();
+ openvdb::io::File file(name);
+ file.open();
+
+ openvdb::GridBase::Ptr baseGrid;
+ for (openvdb::io::File::NameIterator nameIter = file.beginName(); nameIter != file.endName();
+ ++nameIter) {
+# ifndef BLENDER
+ // Read in only the grid we are interested in.
+ if (nameIter.gridName() == grid->getName()) {
+ baseGrid = file.readGrid(nameIter.gridName());
+ }
+ else {
+ debMsg("skipping grid " << nameIter.gridName(), 1);
+ }
+# else
+ // For Blender, skip name check and pick first grid from loop
+ baseGrid = file.readGrid(nameIter.gridName());
+ break;
+# endif
+ }
+ file.close();
+ openvdb::FloatGrid::Ptr gridVDB = openvdb::gridPtrCast<openvdb::FloatGrid>(baseGrid);
+
+ openvdb::FloatGrid::Accessor accessor = gridVDB->getAccessor();
+
+ FOR_IJK(*grid)
+ {
+ openvdb::Coord xyz(i, j, k);
+ float v = accessor.getValue(xyz);
+ (*grid)(i, j, k) = v;
+ }
+};
+
+template<> void writeGridVDB(const string &name, Grid<Vec3> *grid)
+{
+ debMsg("Writing vec3 grid " << grid->getName() << " to vdb file " << name, 1);
+
+ openvdb::initialize();
+ openvdb::Vec3SGrid::Ptr gridVDB = openvdb::Vec3SGrid::create();
+ // note , warning - velocity content currently not scaled...
+ gridVDB->setTransform(
+ openvdb::math::Transform::createLinearTransform(1. / grid->getSizeX())); // voxel size
+ openvdb::Vec3SGrid::Accessor accessor = gridVDB->getAccessor();
+
+ // MAC or regular vec grid?
+ if (grid->getType() & GridBase::TypeMAC)
+ gridVDB->setGridClass(openvdb::GRID_STAGGERED);
+ else
+ gridVDB->setGridClass(openvdb::GRID_UNKNOWN);
+
+ gridVDB->setName(grid->getName());
+
+ openvdb::io::File file(name);
+ FOR_IJK(*grid)
+ {
+ openvdb::Coord xyz(i, j, k);
+ Vec3 v = (*grid)(i, j, k);
+ openvdb::Vec3f vo((float)v[0], (float)v[1], (float)v[2]);
+ accessor.setValue(xyz, vo);
+ }
+
+ openvdb::GridPtrVec gridsVDB;
+ gridsVDB.push_back(gridVDB);
+
+ file.write(gridsVDB);
+ file.close();
+};
+
+template<> void readGridVDB(const string &name, Grid<Vec3> *grid)
+{
+ debMsg("Reading vec3 grid " << grid->getName() << " from vdb file " << name, 1);
+
+ openvdb::initialize();
+ openvdb::io::File file(name);
+ file.open();
+
+ openvdb::GridBase::Ptr baseGrid;
+ for (openvdb::io::File::NameIterator nameIter = file.beginName(); nameIter != file.endName();
+ ++nameIter) {
+# ifndef BLENDER
+ // Read in only the grid we are interested in.
+ if (nameIter.gridName() == grid->getName()) {
+ baseGrid = file.readGrid(nameIter.gridName());
+ }
+ else {
+ debMsg("skipping grid " << nameIter.gridName(), 1);
+ }
+# else
+ // For Blender, skip name check and pick first grid from loop
+ baseGrid = file.readGrid(nameIter.gridName());
+ break;
+# endif
+ }
+ file.close();
+ openvdb::Vec3SGrid::Ptr gridVDB = openvdb::gridPtrCast<openvdb::Vec3SGrid>(baseGrid);
+
+ openvdb::Vec3SGrid::Accessor accessor = gridVDB->getAccessor();
+
+ FOR_IJK(*grid)
+ {
+ openvdb::Coord xyz(i, j, k);
+ openvdb::Vec3f v = accessor.getValue(xyz);
+ (*grid)(i, j, k).x = (float)v[0];
+ (*grid)(i, j, k).y = (float)v[1];
+ (*grid)(i, j, k).z = (float)v[2];
+ }
+};
+
+#endif // OPENVDB==1
+
+//*****************************************************************************
+// npz file support (warning - read works, but write generates uncompressed npz; i.e. not
+// recommended for large volumes)
+
+template<class T> void writeGridNumpy(const string &name, Grid<T> *grid)
+{
+#if NO_ZLIB == 1
+ debMsg("file format not supported without zlib", 1);
+ return;
+#endif
+#if FLOATINGPOINT_PRECISION != 1
+ errMsg("writeGridNumpy: Double precision not yet supported");
+#endif
+
+ // find suffix to differentiate between npy <-> npz , TODO: check for actual "npy" string
+ std::string::size_type idx;
+ bool bUseNpz = false;
+ idx = name.rfind('.');
+ if (idx != std::string::npos) {
+ bUseNpz = name.substr(idx + 1) == "npz";
+ debMsg("Writing grid " << grid->getName() << " to npz file " << name, 1);
+ }
+ else {
+ debMsg("Writing grid " << grid->getName() << " to npy file " << name, 1);
+ }
+
+ // storage code
+ size_t uDim = 1;
+ if (grid->getType() & GridBase::TypeInt || grid->getType() & GridBase::TypeReal ||
+ grid->getType() & GridBase::TypeLevelset)
+ uDim = 1;
+ else if (grid->getType() & GridBase::TypeVec3 || grid->getType() & GridBase::TypeMAC)
+ uDim = 3;
+ else
+ errMsg("writeGridNumpy: unknown element type");
+
+ const std::vector<size_t> shape = {static_cast<size_t>(grid->getSizeZ()),
+ static_cast<size_t>(grid->getSizeY()),
+ static_cast<size_t>(grid->getSizeX()),
+ uDim};
+
+ if (bUseNpz) {
+ // note, the following generates a zip file without compression
+ if (grid->getType() & GridBase::TypeVec3 || grid->getType() & GridBase::TypeMAC) {
+ // cast to float* for export!
+ float *ptr = (float *)&((*grid)[0]);
+ cnpy::npz_save(name, "arr_0", ptr, shape, "w");
+ }
+ else {
+ T *ptr = &((*grid)[0]);
+ cnpy::npz_save(name, "arr_0", ptr, shape, "w");
+ }
+ }
+ else {
+ cnpy::npy_save(name, &grid[0], shape, "w");
+ }
+};
+
+template<class T> void readGridNumpy(const string &name, Grid<T> *grid)
+{
+#if NO_ZLIB == 1
+ debMsg("file format not supported without zlib", 1);
+ return;
+#endif
+#if FLOATINGPOINT_PRECISION != 1
+ errMsg("readGridNumpy: Double precision not yet supported");
+#endif
+
+ // find suffix to differentiate between npy <-> npz
+ std::string::size_type idx;
+ bool bUseNpz = false;
+ idx = name.rfind('.');
+ if (idx != std::string::npos) {
+ bUseNpz = name.substr(idx + 1) == "npz";
+ debMsg("Reading grid " << grid->getName() << " as npz file " << name, 1);
+ }
+ else {
+ debMsg("Reading grid " << grid->getName() << " as npy file " << name, 1);
+ }
+
+ cnpy::NpyArray gridArr;
+ if (bUseNpz) {
+ cnpy::npz_t fNpz = cnpy::npz_load(name);
+ gridArr = fNpz["arr_0"];
+ }
+ else {
+ gridArr = cnpy::npy_load(name);
+ }
+
+ // Check the file meta information
+ assertMsg(gridArr.shape[2] == grid->getSizeX() && gridArr.shape[1] == grid->getSizeY() &&
+ gridArr.shape[0] == grid->getSizeZ(),
+ "grid dim doesn't match, "
+ << Vec3(gridArr.shape[2], gridArr.shape[1], gridArr.shape[0]) << " vs "
+ << grid->getSize());
+ size_t uDim = 1;
+ if (grid->getType() & GridBase::TypeInt || grid->getType() & GridBase::TypeReal ||
+ grid->getType() & GridBase::TypeLevelset)
+ uDim = 1;
+ else if (grid->getType() & GridBase::TypeVec3 || grid->getType() & GridBase::TypeMAC)
+ uDim = 3;
+ else
+ errMsg("readGridNumpy: unknown element type");
+ assertMsg(gridArr.shape[3] == uDim,
+ "grid data dim doesn't match, " << gridArr.shape[3] << " vs " << uDim);
+
+ if (grid->getType() & GridBase::TypeVec3 || grid->getType() & GridBase::TypeMAC) {
+ // treated as float* for export , thus consider 3 elements
+ assertMsg(3 * gridArr.word_size == sizeof(T),
+ "vec3 grid data size doesn't match, " << 3 * gridArr.word_size << " vs "
+ << sizeof(T));
+ }
+ else {
+ assertMsg(gridArr.word_size == sizeof(T),
+ "grid data size doesn't match, " << gridArr.word_size << " vs " << sizeof(T));
+ }
+
+ // copy back, TODO: beautify...
+ memcpy(&((*grid)[0]),
+ gridArr.data<T>(),
+ sizeof(T) * grid->getSizeX() * grid->getSizeY() * grid->getSizeZ());
+};
+
+// adopted from getUniFileSize
+void getNpzFileSize(
+ const string &name, int &x, int &y, int &z, int *t = NULL, std::string *info = NULL)
+{
+ x = y = z = 0;
+#if NO_ZLIB != 1
+ debMsg("file format not supported without zlib", 1);
+ return;
+#endif
+#if FLOATINGPOINT_PRECISION != 1
+ errMsg("getNpzFileSize: Double precision not yet supported");
+#endif
+ // find suffix to differentiate between npy <-> npz
+ cnpy::NpyArray gridArr;
+ cnpy::npz_t fNpz = cnpy::npz_load(name);
+ gridArr = fNpz["arr_0"];
+
+ z = gridArr.shape[0];
+ y = gridArr.shape[1];
+ x = gridArr.shape[2];
+ if (t)
+ (*t) = 0; // unused for now
+}
+Vec3 getNpzFileSize(const string &name)
+{
+ int x, y, z;
+ getNpzFileSize(name, x, y, z);
+ return Vec3(Real(x), Real(y), Real(z));
+}
+static PyObject *_W_2(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
+{
+ try {
+ PbArgs _args(_linargs, _kwds);
+ FluidSolver *parent = _args.obtainParent();
+ bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
+ pbPreparePlugin(parent, "getNpzFileSize", !noTiming);
+ PyObject *_retval = 0;
+ {
+ ArgLocker _lock;
+ const string &name = _args.get<string>("name", 0, &_lock);
+ _retval = toPy(getNpzFileSize(name));
+ _args.check();
+ }
+ pbFinalizePlugin(parent, "getNpzFileSize", !noTiming);
+ return _retval;
+ }
+ catch (std::exception &e) {
+ pbSetError("getNpzFileSize", e.what());
+ return 0;
+ }
+}
+static const Pb::Register _RP_getNpzFileSize("", "getNpzFileSize", _W_2);
+extern "C" {
+void PbRegister_getNpzFileSize()
+{
+ KEEP_UNUSED(_RP_getNpzFileSize);
+}
+}
+
+//*****************************************************************************
+// helper functions
+
+void quantizeReal(Real &v, const Real step)
+{
+ int q = int(v / step + step * 0.5);
+ double qd = q * (double)step;
+ v = (Real)qd;
+}
+struct knQuantize : public KernelBase {
+ knQuantize(Grid<Real> &grid, Real step) : KernelBase(&grid, 0), grid(grid), step(step)
+ {
+ runMessage();
+ run();
+ }
+ inline void op(IndexInt idx, Grid<Real> &grid, Real step) const
+ {
+ quantizeReal(grid(idx), step);
+ }
+ inline Grid<Real> &getArg0()
+ {
+ return grid;
+ }
+ typedef Grid<Real> type0;
+ inline Real &getArg1()
+ {
+ return step;
+ }
+ typedef Real type1;
+ void runMessage()
+ {
+ debMsg("Executing kernel knQuantize ", 3);
+ debMsg("Kernel range"
+ << " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
+ 4);
+ };
+ void operator()(const tbb::blocked_range<IndexInt> &__r) const
+ {
+ for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
+ op(idx, grid, step);
+ }
+ void run()
+ {
+ tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
+ }
+ Grid<Real> &grid;
+ Real step;
+};
+void quantizeGrid(Grid<Real> &grid, Real step)
+{
+ knQuantize(grid, step);
+}
+static PyObject *_W_3(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
+{
+ try {
+ PbArgs _args(_linargs, _kwds);
+ FluidSolver *parent = _args.obtainParent();
+ bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
+ pbPreparePlugin(parent, "quantizeGrid", !noTiming);
+ PyObject *_retval = 0;
+ {
+ ArgLocker _lock;
+ Grid<Real> &grid = *_args.getPtr<Grid<Real>>("grid", 0, &_lock);
+ Real step = _args.get<Real>("step", 1, &_lock);
+ _retval = getPyNone();
+ quantizeGrid(grid, step);
+ _args.check();
+ }
+ pbFinalizePlugin(parent, "quantizeGrid", !noTiming);
+ return _retval;
+ }
+ catch (std::exception &e) {
+ pbSetError("quantizeGrid", e.what());
+ return 0;
+ }
+}
+static const Pb::Register _RP_quantizeGrid("", "quantizeGrid", _W_3);
+extern "C" {
+void PbRegister_quantizeGrid()
+{
+ KEEP_UNUSED(_RP_quantizeGrid);
+}
+}
+
+struct knQuantizeVec3 : public KernelBase {
+ knQuantizeVec3(Grid<Vec3> &grid, Real step) : KernelBase(&grid, 0), grid(grid), step(step)
+ {
+ runMessage();
+ run();
+ }
+ inline void op(IndexInt idx, Grid<Vec3> &grid, Real step) const
+ {
+ for (int c = 0; c < 3; ++c)
+ quantizeReal(grid(idx)[c], step);
+ }
+ inline Grid<Vec3> &getArg0()
+ {
+ return grid;
+ }
+ typedef Grid<Vec3> type0;
+ inline Real &getArg1()
+ {
+ return step;
+ }
+ typedef Real type1;
+ void runMessage()
+ {
+ debMsg("Executing kernel knQuantizeVec3 ", 3);
+ debMsg("Kernel range"
+ << " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ",
+ 4);
+ };
+ void operator()(const tbb::blocked_range<IndexInt> &__r) const
+ {
+ for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
+ op(idx, grid, step);
+ }
+ void run()
+ {
+ tbb::parallel_for(tbb::blocked_range<IndexInt>(0, size), *this);
+ }
+ Grid<Vec3> &grid;
+ Real step;
+};
+void quantizeGridVec3(Grid<Vec3> &grid, Real step)
+{
+ knQuantizeVec3(grid, step);
+}
+static PyObject *_W_4(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
+{
+ try {
+ PbArgs _args(_linargs, _kwds);
+ FluidSolver *parent = _args.obtainParent();
+ bool noTiming = _args.getOpt<bool>("notiming", -1, 0);
+ pbPreparePlugin(parent, "quantizeGridVec3", !noTiming);
+ PyObject *_retval = 0;
+ {
+ ArgLocker _lock;
+ Grid<Vec3> &grid = *_args.getPtr<Grid<Vec3>>("grid", 0, &_lock);
+ Real step = _args.get<Real>("step", 1, &_lock);
+ _retval = getPyNone();
+ quantizeGridVec3(grid, step);
+ _args.check();
+ }
+ pbFinalizePlugin(parent, "quantizeGridVec3", !noTiming);
+ return _retval;
+ }
+ catch (std::exception &e) {
+ pbSetError("quantizeGridVec3", e.what());
+ return 0;
+ }
+}
+static const Pb::Register _RP_quantizeGridVec3("", "quantizeGridVec3", _W_4);
+extern "C" {
+void PbRegister_quantizeGridVec3()
+{
+ KEEP_UNUSED(_RP_quantizeGridVec3);
+}
+}
+
+// explicit instantiation
+template void writeGridRaw<int>(const string &name, Grid<int> *grid);
+template void writeGridRaw<Real>(const string &name, Grid<Real> *grid);
+template void writeGridRaw<Vec3>(const string &name, Grid<Vec3> *grid);
+template void writeGridUni<int>(const string &name, Grid<int> *grid);
+template void writeGridUni<Real>(const string &name, Grid<Real> *grid);
+template void writeGridUni<Vec3>(const string &name, Grid<Vec3> *grid);
+template void writeGridVol<int>(const string &name, Grid<int> *grid);
+template void writeGridVol<Vec3>(const string &name, Grid<Vec3> *grid);
+template void writeGridTxt<int>(const string &name, Grid<int> *grid);
+template void writeGridTxt<Real>(const string &name, Grid<Real> *grid);
+template void writeGridTxt<Vec3>(const string &name, Grid<Vec3> *grid);
+
+template void readGridRaw<int>(const string &name, Grid<int> *grid);
+template void readGridRaw<Real>(const string &name, Grid<Real> *grid);
+template void readGridRaw<Vec3>(const string &name, Grid<Vec3> *grid);
+template void readGridUni<int>(const string &name, Grid<int> *grid);
+template void readGridUni<Real>(const string &name, Grid<Real> *grid);
+template void readGridUni<Vec3>(const string &name, Grid<Vec3> *grid);
+template void readGridVol<int>(const string &name, Grid<int> *grid);
+template void readGridVol<Vec3>(const string &name, Grid<Vec3> *grid);
+
+template void readGrid4dUni<int>(
+ const string &name, Grid4d<int> *grid, int readTslice, Grid4d<int> *slice, void **fileHandle);
+template void readGrid4dUni<Real>(const string &name,
+ Grid4d<Real> *grid,
+ int readTslice,
+ Grid4d<Real> *slice,
+ void **fileHandle);
+template void readGrid4dUni<Vec3>(const string &name,
+ Grid4d<Vec3> *grid,
+ int readTslice,
+ Grid4d<Vec3> *slice,
+ void **fileHandle);
+template void readGrid4dUni<Vec4>(const string &name,
+ Grid4d<Vec4> *grid,
+ int readTslice,
+ Grid4d<Vec4> *slice,
+ void **fileHandle);
+template void writeGrid4dUni<int>(const string &name, Grid4d<int> *grid);
+template void writeGrid4dUni<Real>(const string &name, Grid4d<Real> *grid);
+template void writeGrid4dUni<Vec3>(const string &name, Grid4d<Vec3> *grid);
+template void writeGrid4dUni<Vec4>(const string &name, Grid4d<Vec4> *grid);
+
+template void readGrid4dRaw<int>(const string &name, Grid4d<int> *grid);
+template void readGrid4dRaw<Real>(const string &name, Grid4d<Real> *grid);
+template void readGrid4dRaw<Vec3>(const string &name, Grid4d<Vec3> *grid);
+template void readGrid4dRaw<Vec4>(const string &name, Grid4d<Vec4> *grid);
+template void writeGrid4dRaw<int>(const string &name, Grid4d<int> *grid);
+template void writeGrid4dRaw<Real>(const string &name, Grid4d<Real> *grid);
+template void writeGrid4dRaw<Vec3>(const string &name, Grid4d<Vec3> *grid);
+template void writeGrid4dRaw<Vec4>(const string &name, Grid4d<Vec4> *grid);
+
+template void writeGridNumpy<int>(const string &name, Grid<int> *grid);
+template void writeGridNumpy<Real>(const string &name, Grid<Real> *grid);
+template void writeGridNumpy<Vec3>(const string &name, Grid<Vec3> *grid);
+template void readGridNumpy<int>(const string &name, Grid<int> *grid);
+template void readGridNumpy<Real>(const string &name, Grid<Real> *grid);
+template void readGridNumpy<Vec3>(const string &name, Grid<Vec3> *grid);
+
+#if OPENVDB == 1
+template void writeGridVDB<int>(const string &name, Grid<int> *grid);
+template void writeGridVDB<Vec3>(const string &name, Grid<Vec3> *grid);
+template void writeGridVDB<Real>(const string &name, Grid<Real> *grid);
+
+template void readGridVDB<int>(const string &name, Grid<int> *grid);
+template void readGridVDB<Vec3>(const string &name, Grid<Vec3> *grid);
+template void readGridVDB<Real>(const string &name, Grid<Real> *grid);
+#endif // OPENVDB==1
+
+} // namespace Manta
+
+namespace Manta {
+
+}
diff --git a/extern/mantaflow/preprocessed/fileio/iomeshes.cpp b/extern/mantaflow/preprocessed/fileio/iomeshes.cpp
new file mode 100644
index 00000000000..fc57e2a8c2b
--- /dev/null
+++ b/extern/mantaflow/preprocessed/fileio/iomeshes.cpp
@@ -0,0 +1,490 @@
+
+
+// DO NOT EDIT !
+// This file is generated using the MantaFlow preprocessor (prep generate).
+
+/******************************************************************************
+ *
+ * MantaFlow fluid solver framework
+ * Copyright 2011-2016 Tobias Pfaff, Nils Thuerey
+ *
+ * This program is free software, distributed under the terms of the
+ * Apache License, Version 2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Loading and writing grids and meshes to disk
+ *
+ ******************************************************************************/
+
+#include <iostream>
+#include <fstream>
+#include <cstdlib>
+#if NO_ZLIB != 1
+extern "C" {
+# include <zlib.h>
+}
+#endif
+
+#include "mantaio.h"
+#include "grid.h"
+#include "mesh.h"
+#include "vortexsheet.h"
+#include <cstring>
+
+using namespace std;
+
+namespace Manta {
+
+static const int STR_LEN_PDATA = 256;
+
+//! mdata uni header, v3 (similar to grid header and mdata header)
+typedef struct {
+ int dim; // number of vertices
+ int dimX, dimY, dimZ; // underlying solver resolution (all data in local coordinates!)
+ int elementType, bytesPerElement; // type id and byte size
+ char info[STR_LEN_PDATA]; // mantaflow build information
+ unsigned long long timestamp; // creation time
+} UniMeshHeader;
+
+//*****************************************************************************
+// conversion functions for double precision
+// (note - uni files always store single prec. values)
+//*****************************************************************************
+
+#if NO_ZLIB != 1
+
+template<class T>
+void mdataConvertWrite(gzFile &gzf, MeshDataImpl<T> &mdata, void *ptr, UniMeshHeader &head)
+{
+ errMsg("mdataConvertWrite: unknown type, not yet supported");
+}
+
+template<>
+void mdataConvertWrite(gzFile &gzf, MeshDataImpl<int> &mdata, void *ptr, UniMeshHeader &head)
+{
+ gzwrite(gzf, &head, sizeof(UniMeshHeader));
+ gzwrite(gzf, &mdata[0], sizeof(int) * head.dim);
+}
+template<>
+void mdataConvertWrite(gzFile &gzf, MeshDataImpl<double> &mdata, void *ptr, UniMeshHeader &head)
+{
+ head.bytesPerElement = sizeof(float);
+ gzwrite(gzf, &head, sizeof(UniMeshHeader));
+ float *ptrf = (float *)ptr;
+ for (int i = 0; i < mdata.size(); ++i, ++ptrf) {
+ *ptrf = (float)mdata[i];
+ }
+ gzwrite(gzf, ptr, sizeof(float) * head.dim);
+}
+template<>
+void mdataConvertWrite(gzFile &gzf, MeshDataImpl<Vec3> &mdata, void *ptr, UniMeshHeader &head)
+{
+ head.bytesPerElement = sizeof(Vector3D<float>);
+ gzwrite(gzf, &head, sizeof(UniMeshHeader));
+ float *ptrf = (float *)ptr;
+ for (int i = 0; i < mdata.size(); ++i) {
+ for (int c = 0; c < 3; ++c) {
+ *ptrf = (float)mdata[i][c];
+ ptrf++;
+ }
+ }
+ gzwrite(gzf, ptr, sizeof(Vector3D<float>) * head.dim);
+}
+
+template<class T>
+void mdataReadConvert(gzFile &gzf, MeshDataImpl<T> &grid, void *ptr, int bytesPerElement)
+{
+ errMsg("mdataReadConvert: unknown mdata type, not yet supported");
+}
+
+template<>
+void mdataReadConvert<int>(gzFile &gzf, MeshDataImpl<int> &mdata, void *ptr, int bytesPerElement)
+{
+ gzread(gzf, ptr, sizeof(int) * mdata.size());
+ assertMsg(bytesPerElement == sizeof(int),
+ "mdata element size doesn't match " << bytesPerElement << " vs " << sizeof(int));
+ // int dont change in double precision mode - copy over
+ memcpy(&(mdata[0]), ptr, sizeof(int) * mdata.size());
+}
+
+template<>
+void mdataReadConvert<double>(gzFile &gzf,
+ MeshDataImpl<double> &mdata,
+ void *ptr,
+ int bytesPerElement)
+{
+ gzread(gzf, ptr, sizeof(float) * mdata.size());
+ assertMsg(bytesPerElement == sizeof(float),
+ "mdata element size doesn't match " << bytesPerElement << " vs " << sizeof(float));
+ float *ptrf = (float *)ptr;
+ for (int i = 0; i < mdata.size(); ++i, ++ptrf) {
+ mdata[i] = double(*ptrf);
+ }
+}
+
+template<>
+void mdataReadConvert<Vec3>(gzFile &gzf, MeshDataImpl<Vec3> &mdata, void *ptr, int bytesPerElement)
+{
+ gzread(gzf, ptr, sizeof(Vector3D<float>) * mdata.size());
+ assertMsg(bytesPerElement == sizeof(Vector3D<float>),
+ "mdata element size doesn't match " << bytesPerElement << " vs "
+ << sizeof(Vector3D<float>));
+ float *ptrf = (float *)ptr;
+ for (int i = 0; i < mdata.size(); ++i) {
+ Vec3 v;
+ for (int c = 0; c < 3; ++c) {
+ v[c] = double(*ptrf);
+ ptrf++;
+ }
+ mdata[i] = v;
+ }
+}
+
+#endif // NO_ZLIB!=1
+
+//*****************************************************************************
+// mesh data
+//*****************************************************************************
+
+void readBobjFile(const string &name, Mesh *mesh, bool append)
+{
+ debMsg("reading mesh file " << name, 1);
+ if (!append)
+ mesh->clear();
+ else
+ errMsg("readBobj: append not yet implemented!");
+
+#if NO_ZLIB != 1
+ const Real dx = mesh->getParent()->getDx();
+ const Vec3 gs = toVec3(mesh->getParent()->getGridSize());
+
+ gzFile gzf = gzopen(name.c_str(), "rb1"); // do some compression
+ if (!gzf)
+ errMsg("readBobj: unable to open file");
+
+ // read vertices
+ int num = 0;
+ gzread(gzf, &num, sizeof(int));
+ mesh->resizeNodes(num);
+ debMsg("read mesh , verts " << num, 1);
+ for (int i = 0; i < num; i++) {
+ Vector3D<float> pos;
+ gzread(gzf, &pos.value[0], sizeof(float) * 3);
+ mesh->nodes(i).pos = toVec3(pos);
+
+ // convert to grid space
+ mesh->nodes(i).pos /= dx;
+ mesh->nodes(i).pos += gs * 0.5;
+ }
+
+ // normals
+ num = 0;
+ gzread(gzf, &num, sizeof(int));
+ for (int i = 0; i < num; i++) {
+ Vector3D<float> pos;
+ gzread(gzf, &pos.value[0], sizeof(float) * 3);
+ mesh->nodes(i).normal = toVec3(pos);
+ }
+
+ // read tris
+ num = 0;
+ gzread(gzf, &num, sizeof(int));
+ mesh->resizeTris(num);
+ for (int t = 0; t < num; t++) {
+ for (int j = 0; j < 3; j++) {
+ int trip = 0;
+ gzread(gzf, &trip, sizeof(int));
+ mesh->tris(t).c[j] = trip;
+ }
+ }
+ // note - vortex sheet info ignored for now... (see writeBobj)
+ gzclose(gzf);
+ debMsg("read mesh , triangles " << mesh->numTris() << ", vertices " << mesh->numNodes() << " ",
+ 1);
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+}
+
+void writeBobjFile(const string &name, Mesh *mesh)
+{
+ debMsg("writing mesh file " << name, 1);
+#if NO_ZLIB != 1
+ const Real dx = mesh->getParent()->getDx();
+ const Vec3i gs = mesh->getParent()->getGridSize();
+
+ gzFile gzf = gzopen(name.c_str(), "wb1"); // do some compression
+ if (!gzf)
+ errMsg("writeBobj: unable to open file");
+
+ // write vertices
+ int numVerts = mesh->numNodes();
+ gzwrite(gzf, &numVerts, sizeof(int));
+ for (int i = 0; i < numVerts; i++) {
+ Vector3D<float> pos = toVec3f(mesh->nodes(i).pos);
+ // normalize to unit cube around 0
+ pos -= toVec3f(gs) * 0.5;
+ pos *= dx;
+ gzwrite(gzf, &pos.value[0], sizeof(float) * 3);
+ }
+
+ // normals
+ mesh->computeVertexNormals();
+ gzwrite(gzf, &numVerts, sizeof(int));
+ for (int i = 0; i < numVerts; i++) {
+ Vector3D<float> pos = toVec3f(mesh->nodes(i).normal);
+ gzwrite(gzf, &pos.value[0], sizeof(float) * 3);
+ }
+
+ // write tris
+ int numTris = mesh->numTris();
+ gzwrite(gzf, &numTris, sizeof(int));
+ for (int t = 0; t < numTris; t++) {
+ for (int j = 0; j < 3; j++) {
+ int trip = mesh->tris(t).c[j];
+ gzwrite(gzf, &trip, sizeof(int));
+ }
+ }
+
+ // per vertex smoke densities
+ if (mesh->getType() == Mesh::TypeVortexSheet) {
+ VortexSheetMesh *vmesh = (VortexSheetMesh *)mesh;
+ int densId[4] = {0, 'v', 'd', 'e'};
+ gzwrite(gzf, &densId[0], sizeof(int) * 4);
+
+ // compute densities
+ vector<float> triDensity(numTris);
+ for (int tri = 0; tri < numTris; tri++) {
+ Real area = vmesh->getFaceArea(tri);
+ if (area > 0)
+ triDensity[tri] = vmesh->sheet(tri).smokeAmount;
+ }
+
+ // project triangle data to vertex
+ vector<int> triPerVertex(numVerts);
+ vector<float> density(numVerts);
+ for (int tri = 0; tri < numTris; tri++) {
+ for (int c = 0; c < 3; c++) {
+ int vertex = mesh->tris(tri).c[c];
+ density[vertex] += triDensity[tri];
+ triPerVertex[vertex]++;
+ }
+ }
+
+ // averaged smoke densities
+ for (int point = 0; point < numVerts; point++) {
+ float dens = 0;
+ if (triPerVertex[point] > 0)
+ dens = density[point] / triPerVertex[point];
+ gzwrite(gzf, &dens, sizeof(float));
+ }
+ }
+
+ // vertex flags
+ if (mesh->getType() == Mesh::TypeVortexSheet) {
+ int Id[4] = {0, 'v', 'x', 'f'};
+ gzwrite(gzf, &Id[0], sizeof(int) * 4);
+
+ // averaged smoke densities
+ for (int point = 0; point < numVerts; point++) {
+ float alpha = (mesh->nodes(point).flags & Mesh::NfMarked) ? 1 : 0;
+ gzwrite(gzf, &alpha, sizeof(float));
+ }
+ }
+
+ gzclose(gzf);
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+}
+
+void readObjFile(const std::string &name, Mesh *mesh, bool append)
+{
+ ifstream ifs(name.c_str());
+
+ if (!ifs.good())
+ errMsg("can't open file '" + name + "'");
+
+ if (!append)
+ mesh->clear();
+ int nodebase = mesh->numNodes();
+ int cnt = nodebase;
+ while (ifs.good() && !ifs.eof()) {
+ string id;
+ ifs >> id;
+
+ if (id[0] == '#') {
+ // comment
+ getline(ifs, id);
+ continue;
+ }
+ if (id == "vt") {
+ // tex coord, ignore
+ }
+ else if (id == "vn") {
+ // normals
+ if (!mesh->numNodes())
+ errMsg("invalid amount of nodes");
+ Node n = mesh->nodes(cnt);
+ ifs >> n.normal.x >> n.normal.y >> n.normal.z;
+ cnt++;
+ }
+ else if (id == "v") {
+ // vertex
+ Node n;
+ ifs >> n.pos.x >> n.pos.y >> n.pos.z;
+ mesh->addNode(n);
+ }
+ else if (id == "g") {
+ // group
+ string group;
+ ifs >> group;
+ }
+ else if (id == "f") {
+ // face
+ string face;
+ Triangle t;
+ for (int i = 0; i < 3; i++) {
+ ifs >> face;
+ if (face.find('/') != string::npos)
+ face = face.substr(0, face.find('/')); // ignore other indices
+ int idx = atoi(face.c_str()) - 1;
+ if (idx < 0)
+ errMsg("invalid face encountered");
+ idx += nodebase;
+ t.c[i] = idx;
+ }
+ mesh->addTri(t);
+ }
+ else {
+ // whatever, ignore
+ }
+ // kill rest of line
+ getline(ifs, id);
+ }
+ ifs.close();
+}
+
+// write regular .obj file, in line with bobj.gz output (but only verts & tris for now)
+void writeObjFile(const string &name, Mesh *mesh)
+{
+ const Real dx = mesh->getParent()->getDx();
+ const Vec3i gs = mesh->getParent()->getGridSize();
+
+ ofstream ofs(name.c_str());
+ if (!ofs.good())
+ errMsg("writeObjFile: can't open file " << name);
+
+ ofs << "o MantaMesh\n";
+
+ // write vertices
+ int numVerts = mesh->numNodes();
+ for (int i = 0; i < numVerts; i++) {
+ Vector3D<float> pos = toVec3f(mesh->nodes(i).pos);
+ // normalize to unit cube around 0
+ pos -= toVec3f(gs) * 0.5;
+ pos *= dx;
+ ofs << "v " << pos.value[0] << " " << pos.value[1] << " " << pos.value[2] << " "
+ << "\n";
+ }
+
+ // write normals
+ for (int i = 0; i < numVerts; i++) {
+ Vector3D<float> n = toVec3f(mesh->nodes(i).normal);
+ // normalize to unit cube around 0
+ ofs << "vn " << n.value[0] << " " << n.value[1] << " " << n.value[2] << " "
+ << "\n";
+ }
+
+ // write tris
+ int numTris = mesh->numTris();
+ for (int t = 0; t < numTris; t++) {
+ ofs << "f " << (mesh->tris(t).c[0] + 1) << " " << (mesh->tris(t).c[1] + 1) << " "
+ << (mesh->tris(t).c[2] + 1) << " "
+ << "\n";
+ }
+
+ ofs.close();
+}
+
+template<class T> void readMdataUni(const std::string &name, MeshDataImpl<T> *mdata)
+{
+ debMsg("reading mesh data " << mdata->getName() << " from uni file " << name, 1);
+
+#if NO_ZLIB != 1
+ gzFile gzf = gzopen(name.c_str(), "rb");
+ if (!gzf)
+ errMsg("can't open file " << name);
+
+ char ID[5] = {0, 0, 0, 0, 0};
+ gzread(gzf, ID, 4);
+
+ if (!strcmp(ID, "MD01")) {
+ UniMeshHeader head;
+ assertMsg(gzread(gzf, &head, sizeof(UniMeshHeader)) == sizeof(UniMeshHeader),
+ "can't read file, no header present");
+ assertMsg(head.dim == mdata->size(), "mdata size doesn't match");
+# if FLOATINGPOINT_PRECISION != 1
+ MeshDataImpl<T> temp(mdata->getParent());
+ temp.resize(mdata->size());
+ mdataReadConvert<T>(gzf, *mdata, &(temp[0]), head.bytesPerElement);
+# else
+ assertMsg(((head.bytesPerElement == sizeof(T)) && (head.elementType == 1)),
+ "mdata type doesn't match");
+ IndexInt bytes = sizeof(T) * head.dim;
+ IndexInt readBytes = gzread(gzf, &(mdata->get(0)), sizeof(T) * head.dim);
+ assertMsg(bytes == readBytes,
+ "can't read uni file, stream length does not match, " << bytes << " vs "
+ << readBytes);
+# endif
+ }
+ gzclose(gzf);
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+}
+
+template<class T> void writeMdataUni(const std::string &name, MeshDataImpl<T> *mdata)
+{
+ debMsg("writing mesh data " << mdata->getName() << " to uni file " << name, 1);
+
+#if NO_ZLIB != 1
+ char ID[5] = "MD01";
+ UniMeshHeader head;
+ head.dim = mdata->size();
+ head.bytesPerElement = sizeof(T);
+ head.elementType = 1; // 1 for mesh data, todo - add sub types?
+ snprintf(head.info, STR_LEN_PDATA, "%s", buildInfoString().c_str());
+ MuTime stamp;
+ head.timestamp = stamp.time;
+
+ gzFile gzf = gzopen(name.c_str(), "wb1"); // do some compression
+ if (!gzf)
+ errMsg("can't open file " << name);
+ gzwrite(gzf, ID, 4);
+
+# if FLOATINGPOINT_PRECISION != 1
+ // always write float values, even if compiled with double precision (as for grids)
+ MeshDataImpl<T> temp(mdata->getParent());
+ temp.resize(mdata->size());
+ mdataConvertWrite(gzf, *mdata, &(temp[0]), head);
+# else
+ gzwrite(gzf, &head, sizeof(UniMeshHeader));
+ gzwrite(gzf, &(mdata->get(0)), sizeof(T) * head.dim);
+# endif
+ gzclose(gzf);
+
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+};
+
+// explicit instantiation
+template void writeMdataUni<int>(const std::string &name, MeshDataImpl<int> *mdata);
+template void writeMdataUni<Real>(const std::string &name, MeshDataImpl<Real> *mdata);
+template void writeMdataUni<Vec3>(const std::string &name, MeshDataImpl<Vec3> *mdata);
+template void readMdataUni<int>(const std::string &name, MeshDataImpl<int> *mdata);
+template void readMdataUni<Real>(const std::string &name, MeshDataImpl<Real> *mdata);
+template void readMdataUni<Vec3>(const std::string &name, MeshDataImpl<Vec3> *mdata);
+
+} // namespace Manta
diff --git a/extern/mantaflow/preprocessed/fileio/ioparticles.cpp b/extern/mantaflow/preprocessed/fileio/ioparticles.cpp
new file mode 100644
index 00000000000..432cbc9f100
--- /dev/null
+++ b/extern/mantaflow/preprocessed/fileio/ioparticles.cpp
@@ -0,0 +1,342 @@
+
+
+// DO NOT EDIT !
+// This file is generated using the MantaFlow preprocessor (prep generate).
+
+/******************************************************************************
+ *
+ * MantaFlow fluid solver framework
+ * Copyright 2011-2016 Tobias Pfaff, Nils Thuerey
+ *
+ * This program is free software, distributed under the terms of the
+ * Apache License, Version 2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Loading and writing grids and meshes to disk
+ *
+ ******************************************************************************/
+
+#include <iostream>
+#include <fstream>
+#include <cstdlib>
+#include <cstring>
+#if NO_ZLIB != 1
+extern "C" {
+# include <zlib.h>
+}
+#endif
+
+#include "mantaio.h"
+#include "grid.h"
+#include "particle.h"
+#include "vector4d.h"
+#include "grid4d.h"
+
+using namespace std;
+
+namespace Manta {
+
+static const int STR_LEN_PDATA = 256;
+
+//! pdata uni header, v3 (similar to grid header)
+typedef struct {
+ int dim; // number of partilces
+ int dimX, dimY, dimZ; // underlying solver resolution (all data in local coordinates!)
+ int elementType, bytesPerElement; // type id and byte size
+ char info[STR_LEN_PDATA]; // mantaflow build information
+ unsigned long long timestamp; // creation time
+} UniPartHeader;
+
+//*****************************************************************************
+// conversion functions for double precision
+// (note - uni files always store single prec. values)
+//*****************************************************************************
+
+#if NO_ZLIB != 1
+
+template<class T>
+void pdataConvertWrite(gzFile &gzf, ParticleDataImpl<T> &pdata, void *ptr, UniPartHeader &head)
+{
+ errMsg("pdataConvertWrite: unknown type, not yet supported");
+}
+
+template<>
+void pdataConvertWrite(gzFile &gzf, ParticleDataImpl<int> &pdata, void *ptr, UniPartHeader &head)
+{
+ gzwrite(gzf, &head, sizeof(UniPartHeader));
+ gzwrite(gzf, &pdata[0], sizeof(int) * head.dim);
+}
+template<>
+void pdataConvertWrite(gzFile &gzf,
+ ParticleDataImpl<double> &pdata,
+ void *ptr,
+ UniPartHeader &head)
+{
+ head.bytesPerElement = sizeof(float);
+ gzwrite(gzf, &head, sizeof(UniPartHeader));
+ float *ptrf = (float *)ptr;
+ for (int i = 0; i < pdata.size(); ++i, ++ptrf) {
+ *ptrf = (float)pdata[i];
+ }
+ gzwrite(gzf, ptr, sizeof(float) * head.dim);
+}
+template<>
+void pdataConvertWrite(gzFile &gzf, ParticleDataImpl<Vec3> &pdata, void *ptr, UniPartHeader &head)
+{
+ head.bytesPerElement = sizeof(Vector3D<float>);
+ gzwrite(gzf, &head, sizeof(UniPartHeader));
+ float *ptrf = (float *)ptr;
+ for (int i = 0; i < pdata.size(); ++i) {
+ for (int c = 0; c < 3; ++c) {
+ *ptrf = (float)pdata[i][c];
+ ptrf++;
+ }
+ }
+ gzwrite(gzf, ptr, sizeof(Vector3D<float>) * head.dim);
+}
+
+template<class T>
+void pdataReadConvert(gzFile &gzf, ParticleDataImpl<T> &grid, void *ptr, int bytesPerElement)
+{
+ errMsg("pdataReadConvert: unknown pdata type, not yet supported");
+}
+
+template<>
+void pdataReadConvert<int>(gzFile &gzf,
+ ParticleDataImpl<int> &pdata,
+ void *ptr,
+ int bytesPerElement)
+{
+ gzread(gzf, ptr, sizeof(int) * pdata.size());
+ assertMsg(bytesPerElement == sizeof(int),
+ "pdata element size doesn't match " << bytesPerElement << " vs " << sizeof(int));
+ // int dont change in double precision mode - copy over
+ memcpy(&(pdata[0]), ptr, sizeof(int) * pdata.size());
+}
+
+template<>
+void pdataReadConvert<double>(gzFile &gzf,
+ ParticleDataImpl<double> &pdata,
+ void *ptr,
+ int bytesPerElement)
+{
+ gzread(gzf, ptr, sizeof(float) * pdata.size());
+ assertMsg(bytesPerElement == sizeof(float),
+ "pdata element size doesn't match " << bytesPerElement << " vs " << sizeof(float));
+ float *ptrf = (float *)ptr;
+ for (int i = 0; i < pdata.size(); ++i, ++ptrf) {
+ pdata[i] = double(*ptrf);
+ }
+}
+
+template<>
+void pdataReadConvert<Vec3>(gzFile &gzf,
+ ParticleDataImpl<Vec3> &pdata,
+ void *ptr,
+ int bytesPerElement)
+{
+ gzread(gzf, ptr, sizeof(Vector3D<float>) * pdata.size());
+ assertMsg(bytesPerElement == sizeof(Vector3D<float>),
+ "pdata element size doesn't match " << bytesPerElement << " vs "
+ << sizeof(Vector3D<float>));
+ float *ptrf = (float *)ptr;
+ for (int i = 0; i < pdata.size(); ++i) {
+ Vec3 v;
+ for (int c = 0; c < 3; ++c) {
+ v[c] = double(*ptrf);
+ ptrf++;
+ }
+ pdata[i] = v;
+ }
+}
+
+#endif // NO_ZLIB!=1
+
+//*****************************************************************************
+// particles and particle data
+//*****************************************************************************
+
+static const int PartSysSize = sizeof(Vector3D<float>) + sizeof(int);
+
+void writeParticlesUni(const std::string &name, const BasicParticleSystem *parts)
+{
+ debMsg("writing particles " << parts->getName() << " to uni file " << name, 1);
+
+#if NO_ZLIB != 1
+ char ID[5] = "PB02";
+ UniPartHeader head;
+ head.dim = parts->size();
+ Vec3i gridSize = parts->getParent()->getGridSize();
+ head.dimX = gridSize.x;
+ head.dimY = gridSize.y;
+ head.dimZ = gridSize.z;
+ head.bytesPerElement = PartSysSize;
+ head.elementType = 0; // 0 for base data
+ snprintf(head.info, STR_LEN_PDATA, "%s", buildInfoString().c_str());
+ MuTime stamp;
+ head.timestamp = stamp.time;
+
+ gzFile gzf = gzopen(name.c_str(), "wb1"); // do some compression
+ if (!gzf)
+ errMsg("can't open file " << name);
+
+ gzwrite(gzf, ID, 4);
+# if FLOATINGPOINT_PRECISION != 1
+ // warning - hard coded conversion of byte size here...
+ gzwrite(gzf, &head, sizeof(UniPartHeader));
+ for (int i = 0; i < parts->size(); ++i) {
+ Vector3D<float> pos = toVec3f((*parts)[i].pos);
+ int flag = (*parts)[i].flag;
+ gzwrite(gzf, &pos, sizeof(Vector3D<float>));
+ gzwrite(gzf, &flag, sizeof(int));
+ }
+# else
+ assertMsg(sizeof(BasicParticleData) == PartSysSize, "particle data size doesn't match");
+ gzwrite(gzf, &head, sizeof(UniPartHeader));
+ gzwrite(gzf, &((*parts)[0]), PartSysSize * head.dim);
+# endif
+ gzclose(gzf);
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+};
+
+void readParticlesUni(const std::string &name, BasicParticleSystem *parts)
+{
+ debMsg("reading particles " << parts->getName() << " from uni file " << name, 1);
+
+#if NO_ZLIB != 1
+ gzFile gzf = gzopen(name.c_str(), "rb");
+ if (!gzf)
+ errMsg("can't open file " << name);
+
+ char ID[5] = {0, 0, 0, 0, 0};
+ gzread(gzf, ID, 4);
+
+ if (!strcmp(ID, "PB01")) {
+ errMsg("particle uni file format v01 not supported anymore");
+ }
+ else if (!strcmp(ID, "PB02")) {
+ // current file format
+ UniPartHeader head;
+ assertMsg(gzread(gzf, &head, sizeof(UniPartHeader)) == sizeof(UniPartHeader),
+ "can't read file, no header present");
+ assertMsg(((head.bytesPerElement == PartSysSize) && (head.elementType == 0)),
+ "particle type doesn't match");
+
+ // re-allocate all data
+ parts->resizeAll(head.dim);
+
+ assertMsg(head.dim == parts->size(), "particle size doesn't match");
+# if FLOATINGPOINT_PRECISION != 1
+ for (int i = 0; i < parts->size(); ++i) {
+ Vector3D<float> pos;
+ int flag;
+ gzread(gzf, &pos, sizeof(Vector3D<float>));
+ gzread(gzf, &flag, sizeof(int));
+ (*parts)[i].pos = toVec3d(pos);
+ (*parts)[i].flag = flag;
+ }
+# else
+ assertMsg(sizeof(BasicParticleData) == PartSysSize, "particle data size doesn't match");
+ IndexInt bytes = PartSysSize * head.dim;
+ IndexInt readBytes = gzread(gzf, &(parts->getData()[0]), bytes);
+ assertMsg(bytes == readBytes,
+ "can't read uni file, stream length does not match, " << bytes << " vs "
+ << readBytes);
+# endif
+
+ parts->transformPositions(Vec3i(head.dimX, head.dimY, head.dimZ),
+ parts->getParent()->getGridSize());
+ }
+ gzclose(gzf);
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+};
+
+template<class T> void writePdataUni(const std::string &name, ParticleDataImpl<T> *pdata)
+{
+ debMsg("writing particle data " << pdata->getName() << " to uni file " << name, 1);
+
+#if NO_ZLIB != 1
+ char ID[5] = "PD01";
+ UniPartHeader head;
+ head.dim = pdata->size();
+ Vec3i gridSize = pdata->getParent()->getGridSize();
+ head.dimX = gridSize.x;
+ head.dimY = gridSize.y;
+ head.dimZ = gridSize.z;
+ head.bytesPerElement = sizeof(T);
+ head.elementType = 1; // 1 for particle data, todo - add sub types?
+ snprintf(head.info, STR_LEN_PDATA, "%s", buildInfoString().c_str());
+ MuTime stamp;
+ head.timestamp = stamp.time;
+
+ gzFile gzf = gzopen(name.c_str(), "wb1"); // do some compression
+ if (!gzf)
+ errMsg("can't open file " << name);
+ gzwrite(gzf, ID, 4);
+
+# if FLOATINGPOINT_PRECISION != 1
+ // always write float values, even if compiled with double precision (as for grids)
+ ParticleDataImpl<T> temp(pdata->getParent());
+ temp.resize(pdata->size());
+ pdataConvertWrite(gzf, *pdata, &(temp[0]), head);
+# else
+ gzwrite(gzf, &head, sizeof(UniPartHeader));
+ gzwrite(gzf, &(pdata->get(0)), sizeof(T) * head.dim);
+# endif
+ gzclose(gzf);
+
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+};
+
+template<class T> void readPdataUni(const std::string &name, ParticleDataImpl<T> *pdata)
+{
+ debMsg("reading particle data " << pdata->getName() << " from uni file " << name, 1);
+
+#if NO_ZLIB != 1
+ gzFile gzf = gzopen(name.c_str(), "rb");
+ if (!gzf)
+ errMsg("can't open file " << name);
+
+ char ID[5] = {0, 0, 0, 0, 0};
+ gzread(gzf, ID, 4);
+
+ if (!strcmp(ID, "PD01")) {
+ UniPartHeader head;
+ assertMsg(gzread(gzf, &head, sizeof(UniPartHeader)) == sizeof(UniPartHeader),
+ "can't read file, no header present");
+ assertMsg(head.dim == pdata->size(), "pdata size doesn't match");
+# if FLOATINGPOINT_PRECISION != 1
+ ParticleDataImpl<T> temp(pdata->getParent());
+ temp.resize(pdata->size());
+ pdataReadConvert<T>(gzf, *pdata, &(temp[0]), head.bytesPerElement);
+# else
+ assertMsg(((head.bytesPerElement == sizeof(T)) && (head.elementType == 1)),
+ "pdata type doesn't match");
+ IndexInt bytes = sizeof(T) * head.dim;
+ IndexInt readBytes = gzread(gzf, &(pdata->get(0)), sizeof(T) * head.dim);
+ assertMsg(bytes == readBytes,
+ "can't read uni file, stream length does not match, " << bytes << " vs "
+ << readBytes);
+# endif
+ }
+ gzclose(gzf);
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
+}
+
+// explicit instantiation
+template void writePdataUni<int>(const std::string &name, ParticleDataImpl<int> *pdata);
+template void writePdataUni<Real>(const std::string &name, ParticleDataImpl<Real> *pdata);
+template void writePdataUni<Vec3>(const std::string &name, ParticleDataImpl<Vec3> *pdata);
+template void readPdataUni<int>(const std::string &name, ParticleDataImpl<int> *pdata);
+template void readPdataUni<Real>(const std::string &name, ParticleDataImpl<Real> *pdata);
+template void readPdataUni<Vec3>(const std::string &name, ParticleDataImpl<Vec3> *pdata);
+
+} // namespace Manta
diff --git a/extern/mantaflow/preprocessed/fileio/mantaio.h b/extern/mantaflow/preprocessed/fileio/mantaio.h
new file mode 100644
index 00000000000..8bb0a5af6a4
--- /dev/null
+++ b/extern/mantaflow/preprocessed/fileio/mantaio.h
@@ -0,0 +1,81 @@
+
+
+// DO NOT EDIT !
+// This file is generated using the MantaFlow preprocessor (prep generate).
+
+/******************************************************************************
+ *
+ * MantaFlow fluid solver framework
+ * Copyright 2011 Tobias Pfaff, Nils Thuerey
+ *
+ * This program is free software, distributed under the terms of the
+ * Apache License, Version 2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Loading and writing grids and meshes to disk
+ *
+ ******************************************************************************/
+
+#ifndef _FILEIO_H
+#define _FILEIO_H
+
+#include <string>
+
+namespace Manta {
+
+// forward decl.
+class Mesh;
+class FlagGrid;
+template<class T> class Grid;
+template<class T> class Grid4d;
+class BasicParticleSystem;
+template<class T> class ParticleDataImpl;
+template<class T> class MeshDataImpl;
+
+void writeObjFile(const std::string &name, Mesh *mesh);
+void writeBobjFile(const std::string &name, Mesh *mesh);
+void readObjFile(const std::string &name, Mesh *mesh, bool append);
+void readBobjFile(const std::string &name, Mesh *mesh, bool append);
+
+template<class T> void writeGridRaw(const std::string &name, Grid<T> *grid);
+template<class T> void writeGridUni(const std::string &name, Grid<T> *grid);
+template<class T> void writeGridVol(const std::string &name, Grid<T> *grid);
+template<class T> void writeGridTxt(const std::string &name, Grid<T> *grid);
+
+#if OPENVDB == 1
+template<class T> void writeGridVDB(const std::string &name, Grid<T> *grid);
+template<class T> void readGridVDB(const std::string &name, Grid<T> *grid);
+#endif // OPENVDB==1
+template<class T> void writeGridNumpy(const std::string &name, Grid<T> *grid);
+template<class T> void readGridNumpy(const std::string &name, Grid<T> *grid);
+
+template<class T> void readGridUni(const std::string &name, Grid<T> *grid);
+template<class T> void readGridRaw(const std::string &name, Grid<T> *grid);
+template<class T> void readGridVol(const std::string &name, Grid<T> *grid);
+
+template<class T> void writeGrid4dUni(const std::string &name, Grid4d<T> *grid);
+template<class T>
+void readGrid4dUni(const std::string &name,
+ Grid4d<T> *grid,
+ int readTslice = -1,
+ Grid4d<T> *slice = NULL,
+ void **fileHandle = NULL);
+void readGrid4dUniCleanup(void **fileHandle);
+template<class T> void writeGrid4dRaw(const std::string &name, Grid4d<T> *grid);
+template<class T> void readGrid4dRaw(const std::string &name, Grid4d<T> *grid);
+
+void writeParticlesUni(const std::string &name, const BasicParticleSystem *parts);
+void readParticlesUni(const std::string &name, BasicParticleSystem *parts);
+
+template<class T> void writePdataUni(const std::string &name, ParticleDataImpl<T> *pdata);
+template<class T> void readPdataUni(const std::string &name, ParticleDataImpl<T> *pdata);
+
+template<class T> void writeMdataUni(const std::string &name, MeshDataImpl<T> *mdata);
+template<class T> void readMdataUni(const std::string &name, MeshDataImpl<T> *mdata);
+
+void getUniFileSize(
+ const std::string &name, int &x, int &y, int &z, int *t = NULL, std::string *info = NULL);
+
+} // namespace Manta
+
+#endif
diff --git a/extern/mantaflow/preprocessed/fileio/mantaio.h.reg.cpp b/extern/mantaflow/preprocessed/fileio/mantaio.h.reg.cpp
new file mode 100644
index 00000000000..6520786181e
--- /dev/null
+++ b/extern/mantaflow/preprocessed/fileio/mantaio.h.reg.cpp
@@ -0,0 +1,13 @@
+
+
+// DO NOT EDIT !
+// This file is generated using the MantaFlow preprocessor (prep link).
+
+#include "fileio/mantaio.h"
+namespace Manta {
+extern "C" {
+void PbRegister_file_18()
+{
+}
+}
+} // namespace Manta \ No newline at end of file