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>2019-12-16 17:40:15 +0300
committerSebastián Barschkis <sebbas@sebbas.org>2019-12-16 18:27:26 +0300
commit4ff7c5eed6b546ae42692f3a869a5ccc095a9cb4 (patch)
tree03f8233788ae46e66672f711e3cf42d8d00d01cc /extern/mantaflow/preprocessed/fileio
parent6a3f2b30d206df23120cd212132adea821b6c20e (diff)
Mantaflow [Part 1]: Added preprocessed Mantaflow source files
Includes preprocessed Mantaflow source files for both OpenMP and TBB (if OpenMP is not present, TBB files will be used instead). These files come directly from the Mantaflow repository. Future updates to the core fluid solver will take place by updating the files. Reviewed By: sergey, mont29 Maniphest Tasks: T59995 Differential Revision: https://developer.blender.org/D3850
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